public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code
@ 2024-01-26 13:10 Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
                   ` (32 more replies)
  0 siblings, 33 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:10 UTC (permalink / raw)
  To: devel

From: Duke Zhai <Duke.Zhai@amd.com>

In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  This AMD reference platform BIOS supports AMD Vangogh B0 SOC and Chachani board.

Duke Zhai (32):
  AMD/AmdPlatformPkg: Check in AMD S3 logo
  AMD/VanGoghBoard: Check in ACPI tables
  AMD/VanGoghBoard: Check in Capsule update
  AMD/VanGoghBoard: Check in AgesaPublic pkg
  AMD/VanGoghBoard: Check in PlatformSecLib
  AMD/VanGoghBoard: Check in AmdIdsExtLib
  AMD/VanGoghBoard: Check in PciPlatform
  AMD/VanGoghBoard: Check in UDKFlashUpdate
  AMD/VanGoghBoard: Check in Flash_AB
  AMD/VanGoghBoard: Check in FlashUpdate
  AMD/VanGoghBoard: Check in FvbServices
  AMD/VanGoghBoard: Check in AMD BaseSerialPortLib
  AMD/VanGoghBoard: Check in PlatformFlashAccessLib
  AMD/VanGoghBoard: Check in SmbiosLib
  AMD/VanGoghBoard: Check in SpiFlashDeviceLib
  AMD/VanGoghBoard: Check in BaseTscTimerLib
  AMD/VanGoghBoard: Check in Smm access module
  AMD/VanGoghBoard: Check in PciHostBridge module
  AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe  module
  AMD/VanGoghBoard: Check in FTPM module
  AMD/VanGoghBoard: Check in SignedCapsule
  AMD/VanGoghBoard: Check in Vtf0
  AMD/VanGoghBoard: Check in AcpiPlatform
  AMD/VanGoghBoard: Check in FchSpi module
  AMD/VanGoghBoard: Check in PlatformInitPei module
  AMD/VanGoghBoard: Check in Smbios platform dxe drivers
  AMD/VanGoghBoard: Check in Fsp2WrapperPkg
  AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module
  AMD/VanGoghBoard: Check in SmramSaveState module
  AMD/VanGoghBoard: Check in EDK2 override files
  AMD/VanGoghBoard: Check in AMD SmmControlPei module
  AMD/VanGoghBoard: Check in Chachani board project files and build
    script

 .../AmdPlatformPkg/Universal/LogoDxe/Logo.c   |  198 +
 .../Universal/LogoDxe/S3Logo.bmp              |  Bin 0 -> 964114 bytes
 .../Universal/LogoDxe/S3Logo.idf              |    9 +
 .../Universal/LogoDxe/S3LogoDxe.inf           |   55 +
 .../VanGoghBoard/AgesaPublic/AgesaPublic.dec  |   61 +
 .../VanGoghBoard/AgesaPublic/Include/AGESA.h  |   35 +
 .../VanGoghBoard/AgesaPublic/Include/AMD.h    |  189 +
 .../AgesaPublic/Include/AmdPspDirectory.h     |   55 +
 .../AgesaPublic/Include/FchRegistersCommon.h  |   23 +
 .../Include/Guid/AmdMemoryInfoHob.h           |   51 +
 .../Include/Library/AmdPspBaseLibV2.h         |  248 +
 .../Include/Library/AmdPspCommonLib.h         |   29 +
 .../Include/Library/AmdPspFtpmLib.h           |   94 +
 .../AgesaPublic/Include/Ppi/AmdPspFtpmPpi.h   |   80 +
 .../Include/Protocol/AmdPspFtpmProtocol.h     |  112 +
 .../Acpi/AcpiTables/AcpiTables.inf            |   33 +
 .../Acpi/AcpiTables/Dsdt/CPU.asl              |   22 +
 .../Acpi/AcpiTables/Dsdt/Dsdt.asl             |   36 +
 .../Acpi/AcpiTables/Dsdt/FchShang.asi         |  927 ++
 .../Acpi/AcpiTables/Dsdt/GloblNvs.asl         |   17 +
 .../Acpi/AcpiTables/Dsdt/HOST_BUS.ASL         |  209 +
 .../Acpi/AcpiTables/Dsdt/LINK.ASL             |  481 ++
 .../Acpi/AcpiTables/Dsdt/Lpc0.asl             |  168 +
 .../Acpi/AcpiTables/Dsdt/PciTree.asl          |  776 ++
 .../Acpi/AcpiTables/Dsdt/Platform.asl         |  135 +
 .../Acpi/AcpiTables/Dsdt/_PR.asl              |   36 +
 .../Acpi/AcpiTables/Facs/Facs.h               |   31 +
 .../Acpi/AcpiTables/Facs/Facs50.aslc          |   68 +
 .../Acpi/AcpiTables/Fadt/Fadt.h               |   64 +
 .../Acpi/AcpiTables/Fadt/Fadt50.aslc          |  159 +
 .../Acpi/AcpiTables/Hpet/Hpet.h               |   70 +
 .../Acpi/AcpiTables/Hpet/Hpet50.aslc          |   58 +
 .../Acpi/AcpiTables/Madt/Madt.h               |  114 +
 .../Acpi/AcpiTables/Madt/Madt50.aslc          |  327 +
 .../Acpi/AcpiTables/Mcfg/Mcfg.h               |   61 +
 .../Acpi/AcpiTables/Mcfg/Mcfg50.aslc          |   61 +
 .../BIOSImageDirectory32M.xml                 |   63 +
 .../VanGoghBoard/ChachaniBoardPkg/Board.env   |   23 +
 .../ChachaniBoardPkg/BuildPspImage.bat        |  126 +
 .../SystemFirmwareDescriptor.aslc             |   85 +
 .../SystemFirmwareDescriptor.inf              |   39 +
 .../SystemFirmwareDescriptorPei.c             |   64 +
 .../ChachaniBoardPkg/Conf/ReadMe.txt          |   14 +
 .../ChachaniBoardPkg/Conf/build_rule.txt      |  654 ++
 .../ChachaniBoardPkg/Conf/target.txt          |   73 +
 .../ChachaniBoardPkg/Conf/tools_def.txt       | 7571 +++++++++++++++++
 .../ChachaniBoardPkg/FlashABImage32M.py       |  102 +
 .../ChachaniBoardPkg/GenCapsule.bat           |   81 +
 .../ChachaniBoardPkg/GenFlashABImage.bat      |   39 +
 .../ChachaniBoardPkg/GoZ_ChachaniExt.bat      |   81 +
 .../Include/Library/CapsuleHookLib.h          |   40 +
 .../Include/Protocol/GlobalNvsArea.h          |   63 +
 .../AmdIdsExtLibNull/AmdIdsHookExtLibNull.c   |   33 +
 .../AmdIdsExtLibNull/AmdIdsHookExtLibNull.inf |   39 +
 .../Capsule/CapsuleHookLib/CapsuleHookLib.c   | 1153 +++
 .../Capsule/CapsuleHookLib/CapsuleHookLib.inf |   56 +
 .../PlatformBootManager.c                     |  794 ++
 .../PlatformBootManager.h                     |  150 +
 .../PlatformBootManagerLib.inf                |   89 +
 .../PlatformBootManagerLib/PlatformConsole.c  |  495 ++
 .../PlatformBootManagerLib/PlatformConsole.h  |   69 +
 .../PlatformBootManagerLib/PlatformData.c     |   39 +
 .../Library/PlatformSecLib/Ia32/Flat32.nasm   |  534 ++
 .../Library/PlatformSecLib/Ia32/Platform.inc  |   53 +
 .../Library/PlatformSecLib/PlatformSecLib.c   |  196 +
 .../Library/PlatformSecLib/PlatformSecLib.inf |   61 +
 .../PlatformSecLib/PlatformSecLibModStrs.uni  |   19 +
 .../PciPlatform/CommonHeader.h                |   27 +
 .../PciPlatform/PciPlatform.c                 |  183 +
 .../PciPlatform/PciPlatform.h                 |   89 +
 .../PciPlatform/PciPlatform.inf               |   51 +
 .../ChachaniBoardPkg/PlatformCapsule.dsc      |   37 +
 .../ChachaniBoardPkg/PlatformCapsule.fdf      |   51 +
 .../VanGoghBoard/ChachaniBoardPkg/Project.dec |  130 +
 .../VanGoghBoard/ChachaniBoardPkg/Project.dsc |  972 +++
 .../VanGoghBoard/ChachaniBoardPkg/Project.fdf |  861 ++
 .../ChachaniBoardPkg/PspBuild.bat             |   82 +
 .../VanGoghBoard/ChachaniBoardPkg/build.sh    |  177 +
 .../ChachaniBoardPkg/buildrom.bat             |  105 +
 .../py-GenerateBiosVersion.py                 |  115 +
 .../ChachaniBoardPkg/py-UpdatePspL1DirCksm.py |   68 +
 .../BaseTools/Source/Python/GenFds/Capsule.py |  253 +
 .../edk2/Fsp2WrapperPkg/FSP_Release_Notes.txt |    4 +
 .../edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec    |  161 +
 .../FspWrapperNotifyDxe/FspWrapperNotifyDxe.c |  676 ++
 .../FspWrapperNotifyDxe.inf                   |   75 +
 .../FspWrapperNotifyDxe/LoadBelow4G.c         |  147 +
 .../FspmWrapperPeim/FspmWrapperPeim.c         |  478 ++
 .../FspmWrapperPeim/FspmWrapperPeim.inf       |   92 +
 .../FspsMultiPhaseSiInitDxe.c                 |  206 +
 .../FspsMultiPhaseSiInitDxe.inf               |   74 +
 .../FspsMultiPhaseSiInitDxe/LoadBelow4G.c     |  148 +
 .../FspsWrapperPeim/FspsWrapperPeim.c         |  632 ++
 .../FspsWrapperPeim/FspsWrapperPeim.inf       |   91 +
 .../Include/FspExportedInterfaceHob.h         |  146 +
 .../Include/FspMemoryRegionHob.h              |   15 +
 .../Include/FspSmmDataExchangeBuffer.h        |   24 +
 .../edk2/Fsp2WrapperPkg/Include/FspUpd.h      |   23 +
 .../edk2/Fsp2WrapperPkg/Include/FspmUpd.h     |   66 +
 .../edk2/Fsp2WrapperPkg/Include/FspsUpd.h     |   45 +
 .../edk2/Fsp2WrapperPkg/Include/FsptUpd.h     |   18 +
 .../Include/Library/FspMeasurementLib.h       |   41 +
 .../Include/Library/FspWrapperApiLib.h        |   82 +
 .../Include/Library/FspWrapperApiTestLib.h    |   56 +
 .../Include/Library/FspWrapperHobProcessLib.h |   39 +
 .../Library/FspWrapperMultiPhaseProcessLib.h  |   45 +
 .../Include/Library/FspWrapperPlatformLib.h   |   81 +
 .../Library/FspWrapperPlatformMultiPhaseLib.h |   31 +
 .../Include/MultiPhaseSiPhases.h              |   19 +
 .../Include/Ppi/FspSiliconInitDone.h          |   38 +
 .../Include/Ppi/TopOfTemporaryRam.h           |   15 +
 .../BaseFspMeasurementLib.inf                 |   54 +
 .../BaseFspMeasurementLib/FspMeasurementLib.c |  254 +
 .../BaseFspWrapperApiLib.inf                  |   66 +
 .../BaseFspWrapperApiLib/FspWrapperApiLib.c   |  235 +
 .../IA32/DispatchExecute.c                    |   71 +
 .../X64/DispatchExecute.c                     |  167 +
 .../BaseFspWrapperApiLib/X64/Thunk64To32.nasm |  252 +
 .../BaseFspWrapperApiTestLibNull.inf          |   49 +
 .../FspWrapperApiTestNull.c                   |   60 +
 .../BaseFspWrapperPlatformLibSample.inf       |   72 +
 .../FspWrapperPlatformLibSample.c             |  347 +
 ...aseFspWrapperPlatformMultiPhaseLibNull.inf |   37 +
 .../FspWrapperPlatformMultiPhaseLibNull.c     |   51 +
 .../DxeFspWrapperMultiPhaseProcessLib.c       |  531 ++
 .../DxeFspWrapperMultiPhaseProcessLib.inf     |   79 +
 .../FspWrapperMultiPhaseProcessLib.inf        |   49 +
 .../PeiFspWrapperMultiPhaseProcessLib.c       |  385 +
 .../FspWrapperApiTest.c                       |   85 +
 .../PeiFspWrapperApiTestLib.inf               |   52 +
 .../CommonHeader.h                            |   91 +
 .../FspWrapperHobProcessLibSample.c           | 1439 ++++
 .../MemoryInstall.h                           |  171 +
 .../PeiFspWrapperHobProcessLibSample.inf      |  121 +
 .../SecFspWrapperPlatformSecLibSample/Fsp.h   |   45 +
 .../FspWrapperPlatformSecLibSample.c          |  129 +
 .../Ia32/PeiCoreEntry.nasm                    |  130 +
 .../Ia32/SecEntry.nasm                        |  335 +
 .../Ia32/Stack.nasm                           |   73 +
 .../PlatformInit.c                            |   38 +
 .../SecFspWrapperPlatformSecLibSample.inf     |   87 +
 .../SecGetPerformance.c                       |   84 +
 .../SecPlatformInformation.c                  |   78 +
 .../SecRamInitData.c                          |   63 +
 .../SecTempRamDone.c                          |   43 +
 .../X64/PeiCoreEntry.nasm                     |  149 +
 .../X64/SecEntry.nasm                         |  173 +
 .../X64/Stack.nasm                            |   73 +
 .../PrepareForFspSmmDxe/PrepareForFspSmmDxe.c |  152 +
 .../PrepareForFspSmmDxe.inf                   |   57 +
 .../PrepareForFspSmmDxeFsp.c                  |   86 +
 .../PrepareForFspSmmDxeFsp.inf                |   49 +
 .../Bus/Pci/PciHostBridgeDxe/IoFifo.h         |  170 +
 .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c  | 1370 +++
 .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.h  |  624 ++
 .../Pci/PciHostBridgeDxe/PciHostBridge.uni    |  Bin 0 -> 1290 bytes
 .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf |   54 +
 .../PciHostBridgeDxe/PciHostBridgeExtra.uni   |  Bin 0 -> 826 bytes
 .../Pci/PciHostBridgeDxe/PciRootBridgeIo.c    | 2421 ++++++
 .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf   |  115 +
 .../CapsuleRuntimeDxe/CapsuleService.c        |  461 +
 .../CapsuleRuntimeDxe/CapsuleService.h        |   73 +
 .../edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c | 1520 ++++
 .../MdeModulePkg/Universal/PCD/Dxe/Pcd.inf    |  359 +
 .../edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c | 1876 ++++
 .../MdeModulePkg/Universal/PCD/Pei/Pcd.inf    |  361 +
 .../Register/Intel/SmramSaveStateMap.h        |  324 +
 .../PcatRealTimeClockRuntimeDxe/PcRtc.c       | 1341 +++
 .../PcatRealTimeClockRuntimeDxe/PcRtc.h       |  374 +
 .../PcatRealTimeClockRuntimeDxe/PcRtc.uni     |   17 +
 .../PcatRealTimeClockRuntimeDxe/PcRtcEntry.c  |  171 +
 .../PcRtcExtra.uni                            |   15 +
 .../PcatRealTimeClockRuntimeDxe.inf           |   77 +
 .../DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c   |  113 +
 .../DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf |   48 +
 .../PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c   |  141 +
 .../PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf |   47 +
 .../AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c |  108 +
 .../Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf       |   43 +
 .../Tpm2InstanceLibAmdFTpm.inf                |   53 +
 .../Tpm2InstanceLibAmdFTpmDxe.c               |  109 +
 .../Tpm2InstanceLibAmdFTpmPei.c               |  153 +
 .../DxeTcg2PhysicalPresenceLib.c              | 1269 +++
 .../DxeTcg2PhysicalPresenceLib.inf            |   68 +
 .../DxeTcg2PhysicalPresenceLib.uni            |   22 +
 .../PhysicalPresenceStrings.uni               |   57 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c         |  854 ++
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h         |  123 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf       |   92 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni       |   19 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni  |   15 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl           |  397 +
 .../Tcg/Tcg2Config/Tcg2ConfigNvData.h         |  124 +
 .../Tcg/Tcg2Config/Tcg2ConfigPei.inf          |   77 +
 .../Tcg/Tcg2Config/Tcg2ConfigPei.uni          |   14 +
 .../Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni     |   15 +
 .../Tcg/Tcg2Config/Tcg2ConfigPeim.c           |  148 +
 .../SecurityPkg/Tcg/Tcg2Config/TpmDetection.c |   99 +
 .../SystemFirmwareUpdate/ParseConfigProfile.c |  217 +
 .../SystemFirmwareCommonDxe.c                 |  371 +
 .../SystemFirmwareUpdate/SystemFirmwareDxe.h  |  421 +
 .../SystemFirmwareUpdateDxe.c                 | 1426 ++++
 .../SystemFirmwareUpdateDxe.inf               |   77 +
 .../SystemFirmwareUpdateDxe.uni               |   15 +
 .../SystemFirmwareUpdateDxeExtra.uni          |   15 +
 .../SmmCpuFeaturesLibCommon.c                 |  623 ++
 .../PiSmmCpuDxeSmm/SmramSaveState.c           |  706 ++
 .../ResetVector/Vtf0/CommonMacros.inc         |   27 +
 .../ResetVector/Vtf0/DebugDisabled.asm        |   21 +
 .../ResetVector/Vtf0/Ia16/Init16.asm          |   51 +
 .../ResetVector/Vtf0/Ia16/Real16ToFlat32.asm  |  138 +
 .../ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm |  108 +
 .../ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm  |   40 +
 .../ResetVector/Vtf0/Ia32/PageTables64.asm    |   25 +
 .../Vtf0/Ia32/SearchForBfvBase.asm            |   84 +
 .../Vtf0/Ia32/SearchForSecEntry.asm           |  195 +
 .../edk2/UefiCpuPkg/ResetVector/Vtf0/Main.asm |  127 +
 .../ResetVector/Vtf0/Port80Debug.asm          |   23 +
 .../UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc |   20 +
 .../ResetVector/Vtf0/ResetVector.uni          |  Bin 0 -> 780 bytes
 .../ResetVector/Vtf0/ResetVectorExtra.uni     |  Bin 0 -> 682 bytes
 .../ResetVector/Vtf0/SerialDebug.asm          |  127 +
 .../edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf |   37 +
 .../UefiCpuPkg/ResetVector/Vtf0/Vtf0.nasmb    |   67 +
 .../ResetVector/Vtf0/X64/PageTables.asm       |   73 +
 Platform/AMD/VanGoghBoard/Readme.md           |   67 +
 Platform/AMD/VanGoghBoard/ReleaseNote.txt     |   14 +
 .../Universal/AcpiPlatformDxe/AcpiPlatform.c  |  336 +
 .../AcpiPlatformDxe/AcpiPlatform.uni          |   15 +
 .../AcpiPlatformDxe/AcpiPlatformDxe.inf       |   59 +
 .../AcpiPlatformDxe/AcpiPlatformExtra.uni     |   13 +
 .../AcpiPlatformDxe/AcpiPlatformHooks.c       |  152 +
 .../AcpiPlatformDxe/AcpiPlatformHooks.h       |   48 +
 .../Universal/FchSpi/FchSpiProtect.c          |   67 +
 .../Universal/FchSpi/FchSpiProtect.h          |   38 +
 .../Universal/FchSpi/FchSpiRuntimeDxe.c       |  163 +
 .../Universal/FchSpi/FchSpiRuntimeDxe.h       |   49 +
 .../Universal/FchSpi/FchSpiRuntimeDxe.inf     |   84 +
 .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.c |  112 +
 .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.h |   32 +
 .../Universal/FchSpi/FchSpiSmm.inf            |   94 +
 .../VanGoghBoard/Universal/FchSpi/SpiCommon.c |  790 ++
 .../VanGoghBoard/Universal/FchSpi/SpiInfo.h   |   24 +
 .../Universal/PlatformInitPei/BootMode.c      |  270 +
 .../Universal/PlatformInitPei/CommonHeader.h  |  226 +
 .../PlatformInitPei/MemoryCallback.c          |  293 +
 .../Universal/PlatformInitPei/MemoryInstall.c |  938 ++
 .../Universal/PlatformInitPei/MemoryInstall.h |  214 +
 .../Universal/PlatformInitPei/MemoryPeim.c    |  352 +
 .../Universal/PlatformInitPei/PlatformInit.c  |  161 +
 .../PlatformInitPei/PlatformInit.inf          |  102 +
 .../Universal/PlatformInitPei/Stall.c         |   89 +
 .../PlatformSmbiosDxe/PlatformSmbiosDxe.c     |   75 +
 .../PlatformSmbiosDxe/PlatformSmbiosDxe.inf   |   52 +
 .../Universal/PlatformSmbiosDxe/SmbiosTable.c |  382 +
 .../VanGoghCommonPkg/AmdCommonPkg.dec         |   57 +
 .../UDKFlashUpdate/SpiFlashDevice.c           |   37 +
 .../UDKFlashUpdate/SpiFlashDevice.h           |   62 +
 .../UDKFlashUpdate/UDKFlashUpdate.c           |  671 ++
 .../UDKFlashUpdate/UDKFlashUpdate.h           |   48 +
 .../UDKFlashUpdate/UDKFlashUpdate.inf         |   51 +
 .../FlashUpdate/FlashUpdateCommon.h           |  143 +
 .../FlashUpdate/FlashUpdateSmm.c              |  512 ++
 .../FlashUpdate/FlashUpdateSmm.h              |  123 +
 .../FlashUpdate/FlashUpdateSmm.inf            |   59 +
 .../FlashUpdate/FlashUpdateSmmRuntimeDxe.c    |  407 +
 .../FlashUpdate/FlashUpdateSmmRuntimeDxe.inf  |   48 +
 .../VanGoghCommonPkg/FlashUpdate/PcRtc.h      |  375 +
 .../ImageSlotHeader/ImageSlotHeader_1.inf     |   34 +
 .../ImageSlotHeader/ImageSlotHeader_1.nasmb   |   18 +
 .../ImageSlotHeader/ImageSlotHeader_2.inf     |   34 +
 .../ImageSlotHeader/ImageSlotHeader_2.nasmb   |   18 +
 .../Flash_AB/NewEFS/NewEFS.inf                |   26 +
 .../Flash_AB/NewEFS/NewEFS.nasmb              |   40 +
 .../PspL1Directory/PspL1Directory.inf         |   38 +
 .../PspL1Directory/PspL1Directory.nasmb       |   28 +
 .../VanGoghCommonPkg/FvbServices/FvbInfo.c    |  120 +
 .../FvbServices/FwBlockService.c              | 1285 +++
 .../FvbServices/FwBlockService.h              |  515 ++
 .../FvbServices/PlatformSmmSpi.inf            |   68 +
 .../Include/Library/SmbiosLib.h               |  171 +
 .../Include/Library/SpiFlashDeviceLib.h       |   59 +
 .../Include/OtaCapsuleUpdate.h                |   38 +
 .../VanGoghCommonPkg/Include/Protocol/Spi.h   |  346 +
 .../Include/Protocol/SpiCommon.h              |  247 +
 .../Include/Protocol/SpiFlashUpdate.h         |  152 +
 .../BaseSerialPortLib16550AmdFchUart.c        |  463 +
 .../BaseSerialPortLib16550AmdFchUart.inf      |   40 +
 .../PlatformFlashAccessLib.c                  |  528 ++
 .../PlatformFlashAccessLib.inf                |   52 +
 .../Library/SmbiosLib/SmbiosLib.c             |  322 +
 .../Library/SmbiosLib/SmbiosLib.inf           |   41 +
 .../SpiFlashDeviceLib/SpiFlashDeviceLib.c     |   42 +
 .../SpiFlashDeviceLib/SpiFlashDeviceLib.inf   |   29 +
 .../Library/TscTimerLib/BaseTscTimerLib.c     |   23 +
 .../Library/TscTimerLib/BaseTscTimerLib.inf   |   43 +
 .../Library/TscTimerLib/DxeTscTimerLib.c      |   80 +
 .../Library/TscTimerLib/DxeTscTimerLib.inf    |   55 +
 .../Library/TscTimerLib/PeiTscTimerLib.c      |   53 +
 .../Library/TscTimerLib/PeiTscTimerLib.inf    |   49 +
 .../Library/TscTimerLib/TscTimerLibInternal.h |   53 +
 .../Library/TscTimerLib/TscTimerLibShare.c    |  255 +
 .../Smm/AcpiSmm/AcpiSmmPlatform.c             |  183 +
 .../Smm/AcpiSmm/AcpiSmmPlatform.h             |   50 +
 .../Smm/AcpiSmm/AcpiSmmPlatform.inf           |   57 +
 .../Smm/SmmAccessPei/SmmAccessPei.c           |  436 +
 .../Smm/SmmAccessPei/SmmAccessPei.inf         |   43 +
 .../Smm/SmmControlPei/SmmControlPei.c         |  307 +
 .../Smm/SmmControlPei/SmmControlPei.inf       |   40 +
 309 files changed, 66671 insertions(+)
 create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
 create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
 create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
 create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/AgesaPublic.dec
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/AGESA.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/AMD.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/AmdPspDirectory.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/FchRegistersCommon.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Guid/AmdMemoryInfoHob.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspBaseLibV2.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspCommonLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspFtpmLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Ppi/AmdPspFtpmPpi.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Protocol/AmdPspFtpmProtocol.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/AcpiTables.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/CPU.asl
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/Dsdt.asl
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/FchShang.asi
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/GloblNvs.asl
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/HOST_BUS.ASL
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/LINK.ASL
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/Lpc0.asl
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/PciTree.asl
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/Platform.asl
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Dsdt/_PR.asl
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Facs/Facs.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Facs/Facs50.aslc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Fadt/Fadt.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Fadt/Fadt50.aslc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Hpet/Hpet.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Hpet/Hpet50.aslc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Madt/Madt.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Madt/Madt50.aslc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Mcfg/Mcfg.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Acpi/AcpiTables/Mcfg/Mcfg50.aslc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/BIOSImageDirectory32M.xml
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Board.env
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/BuildPspImage.bat
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.aslc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptorPei.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Conf/ReadMe.txt
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Conf/build_rule.txt
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Conf/target.txt
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Conf/tools_def.txt
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/FlashABImage32M.py
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/GenCapsule.bat
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/GenFlashABImage.bat
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/GoZ_ChachaniExt.bat
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/CapsuleHookLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Protocol/GlobalNvsArea.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManagerLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformData.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Flat32.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Platform.inc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLibModStrs.uni
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/CommonHeader.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PlatformCapsule.dsc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PlatformCapsule.fdf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Project.dec
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Project.dsc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Project.fdf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PspBuild.bat
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/build.sh
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/buildrom.bat
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/py-GenerateBiosVersion.py
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/py-UpdatePspL1DirCksm.py
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFds/Capsule.py
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Release_Notes.txt
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/LoadBelow4G.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspExportedInterfaceHob.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspMemoryRegionHob.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspSmmDataExchangeBuffer.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspUpd.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspmUpd.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspsUpd.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FsptUpd.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspMeasurementLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiTestLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperHobProcessLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperMultiPhaseProcessLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformMultiPhaseLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/MultiPhaseSiPhases.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/FspSiliconInitDone.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/TopOfTemporaryRam.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/FspMeasurementLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPhaseLibNull.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLibNull.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/FspWrapperApiTest.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/CommonHeader.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/MemoryInstall.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Fsp.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/Stack.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/PlatformInit.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecGetPerformance.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecPlatformInformation.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecTempRamDone.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/SecEntry.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/Stack.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/IoFifo.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Intel/SmramSaveStateMap.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmPei.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/CommonMacros.inc
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/DebugDisabled.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/PageTables64.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForBfvBase.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Main.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Port80Debug.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/ResetVector.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/ResetVectorExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/SerialDebug.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.nasmb
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/X64/PageTables.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Readme.md
 create mode 100644 Platform/AMD/VanGoghBoard/ReleaseNote.txt
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h
 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
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/SmbiosTable.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/AmdCommonPkg.dec
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateCommon.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/PcRtc.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Flash_AB/ImageSlotHeader/ImageSlotHeader_1.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Flash_AB/ImageSlotHeader/ImageSlotHeader_1.nasmb
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Flash_AB/ImageSlotHeader/ImageSlotHeader_2.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Flash_AB/ImageSlotHeader/ImageSlotHeader_2.nasmb
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Flash_AB/NewEFS/NewEFS.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Flash_AB/NewEFS/NewEFS.nasmb
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Flash_AB/PspL1Directory/PspL1Directory.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Flash_AB/PspL1Directory/PspL1Directory.nasmb
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FvbInfo.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/PlatformSmmSpi.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SmbiosLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDeviceLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/OtaCapsuleUpdate.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashUpdate.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.inf
 create mode 100644 Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.c
 create mode 100644 Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.inf

-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114576): https://edk2.groups.io/g/devel/message/114576
Mute This Topic: https://groups.io/mt/103975434/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:10 ` Zhai, MingXin (Duke) via groups.io
  2024-01-29 10:37   ` Chang, Abner via groups.io
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 02/32] AMD/VanGoghBoard: Check in ACPI tables Zhai, MingXin (Duke) via groups.io
                   ` (31 subsequent siblings)
  32 siblings, 1 reply; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:10 UTC (permalink / raw)
  To: devel; +Cc: Duke Zhai, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  LogoDxe module displays boot logo.
  S3LogoDxe module is based on EDK2 LogoDxe module and update AMD S3 logo.

Signed-off-by: Eric Xing <eric.xing@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../AmdPlatformPkg/Universal/LogoDxe/Logo.c   | 198 ++++++++++++++++++
 .../Universal/LogoDxe/S3Logo.bmp              | Bin 0 -> 964114 bytes
 .../Universal/LogoDxe/S3Logo.idf              |   9 +
 .../Universal/LogoDxe/S3LogoDxe.inf           |  55 +++++
 4 files changed, 262 insertions(+)
 create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
 create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
 create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
 create mode 100644 Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf

diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
new file mode 100644
index 0000000000..4463ba58eb
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
@@ -0,0 +1,198 @@
+/**
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+**/
+
+/** @file
+  Logo DXE Driver, install Edk2 Platform Logo protocol.
+
+  Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiImageEx.h>
+#include <Protocol/HiiPackageList.h>
+#include <Protocol/PlatformLogo.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BootLogoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include "Logo.h"
+
+EFI_HII_IMAGE_EX_PROTOCOL  *mHiiImageEx;
+EFI_HII_HANDLE             mHiiHandle;
+LOGO_ENTRY                 mLogos[] = {
+  {
+    IMAGE_TOKEN (IMG_LOGO),
+    EdkiiPlatformLogoDisplayAttributeCenter,
+    0,
+    0
+  }
+};
+
+/**
+  Load a platform logo image and return its data and attributes.
+
+  @param[in]      This              The pointer to this protocol instance.
+  @param[in, out] Instance          The visible image instance is found.
+  @param[out]     Image             Points to the image.
+  @param[out]     Attribute         The display attributes of the image returned.
+  @param[out]     OffsetX           The X offset of the image regarding the Attribute.
+  @param[out]     OffsetY           The Y offset of the image regarding the Attribute.
+
+  @retval EFI_SUCCESS            The image was fetched successfully.
+  @retval EFI_NOT_FOUND          The specified image could not be found.
+  @retval EFI_INVALID_PARAMETER  One of the given input parameters are incorrect
+**/
+EFI_STATUS
+EFIAPI
+GetImage (
+  IN     EDKII_PLATFORM_LOGO_PROTOCOL        *This,
+  IN OUT UINT32                              *Instance,
+  OUT EFI_IMAGE_INPUT                        *Image,
+  OUT EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE  *Attribute,
+  OUT INTN                                   *OffsetX,
+  OUT INTN                                   *OffsetY
+  )
+{
+  UINT32  Current;
+
+  if ((Instance == NULL) || (Image == NULL) ||
+      (Attribute == NULL) || (OffsetX == NULL) || (OffsetY == NULL))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Current = *Instance;
+  if (Current >= ARRAY_SIZE (mLogos)) {
+    return EFI_NOT_FOUND;
+  }
+
+  (*Instance)++; // Advance to next logo.
+  *Attribute = mLogos[Current].Attribute;
+  *OffsetX   = mLogos[Current].OffsetX;
+  *OffsetY   = mLogos[Current].OffsetY;
+  return mHiiImageEx->GetImageEx (mHiiImageEx, mHiiHandle, mLogos[Current].ImageId, Image);
+}
+
+EDKII_PLATFORM_LOGO_PROTOCOL  mPlatformLogo = {
+  GetImage
+};
+
+// AMD_EDKII_OVERRIDE START
+
+/**
+  After console ready before boot option event callback
+
+  @param[in] Event      The Event this notify function registered to.
+  @param[in] Context    Pointer to the context data registered to the Event.
+**/
+VOID
+EFIAPI
+LogoDxeDisplayEventCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  DEBUG ((DEBUG_INFO, "AMD logo is displaying.\n"));
+
+  BootLogoEnableLogo ();
+  gBS->CloseEvent (Event);
+}
+
+/**
+  Entrypoint of this module.
+
+  This function is the entrypoint of this module. It installs the Edkii
+  Platform Logo protocol.
+
+  @param  ImageHandle       The firmware allocated handle for the EFI image.
+  @param  SystemTable       A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeLogo (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_HII_PACKAGE_LIST_HEADER  *PackageList;
+  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;
+  EFI_HANDLE                   Handle;
+  EFI_EVENT                    AfterConsoleReadyBeforeBootOptionEvent;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiHiiDatabaseProtocolGuid,
+                  NULL,
+                  (VOID **)&HiiDatabase
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->LocateProtocol (
+                  &gEfiHiiImageExProtocolGuid,
+                  NULL,
+                  (VOID **)&mHiiImageEx
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Retrieve HII package list from ImageHandle
+  //
+  Status = gBS->OpenProtocol (
+                  ImageHandle,
+                  &gEfiHiiPackageListProtocolGuid,
+                  (VOID **)&PackageList,
+                  ImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "HII Image Package with logo not found in PE/COFF resource section\n"));
+    return Status;
+  }
+
+  //
+  // Publish HII package list to HII Database.
+  //
+  Status = HiiDatabase->NewPackageList (
+                          HiiDatabase,
+                          PackageList,
+                          NULL,
+                          &mHiiHandle
+                          );
+  if (!EFI_ERROR (Status)) {
+    Handle = NULL;
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &Handle,
+                    &gEdkiiPlatformLogoProtocolGuid,
+                    &mPlatformLogo,
+                    NULL
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Install protocol failed.\n"));
+      return Status;
+    }
+  }
+
+  //
+  // Create AfterConsoleReadyBeforeBootOption event callback
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  LogoDxeDisplayEventCallback,
+                  NULL,
+                  (EFI_GUID *)PcdGetPtr (PcdAmdDisplayLogoEventGuid),
+                  &AfterConsoleReadyBeforeBootOptionEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..137f4dcebe4ebd77d50f35ed3b31bf76c0f5f55d
GIT binary patch
literal 964114
zcmeI*zjE`um)LP-CmE~SVz0nu`pl&EZ0BMdw`zPTz7I7nJn7S<c9AM=+F#*I*h((8
z@E(#P2?7V_fFLD{^4IUnM<gW@;0M4V_(#;g{@cI&pMTypfB*Bp?sorOUjN5`+wK1U
zKkat^Ww&qV|KorE^X~u3N19>!_qN-~|GT%h?nVBU(cS0g=kD_#pSyqmfB$Q@dwi1N
zRR($E@m+>b8NPPAr=1LsGRVl&s|;^4yvy(@!`E*2x|88ih9?<h;`L32cNsoq_&TTi
zD6da4yvpz<!@CThGJNfJGP-+zl;KH+R~g=9c$eW*hA+wFPKHMro@98H;Z25j89rtB
z+U?~3-PfZGPcpp9@Fv5%44*Q5?Vfg$&E2C6&3~^lyvgt`!>0^i-KIT0%IlL1uQI&J
z@Girr3}4-5KRwFplMJsiyvgt`!>0^i9m(sXygteBD#M!$?=pPK@YQj>J<98o46ic0
z$?z`2rwm^m<@=+&KFRPZ!<!86GJMML)iHlQ%IlL1uQI&J@Girr3}0;#JbgXN>yr$x
zGQ7#~F2kn`U%NNi{<qzu49%9m%Fz7xF2kn`U%R)*oeYmMJjw7X!<!86GJMML)fL;*
zqr5)J@G8Tb4DT|0%J9_{>FcAsKFRPZ!<!86GJMML)fKlS^7i&5!>bH$GQ7+1DZ^J+
z72Y4^^+|?T8Qx@gm*G=}udbSWKFaHp46ic0$?z`2rwm_h6?*%6l-DO2US)Wb;a!GL
z8NPO(vi+aCM;V@Ec$MKzhIbj7|Gv7a_4p{SPcpp9@Fv5%44*Q5b=B_aQC^>9c$MKz
zhIbi0W%%l<<m;onKFRPZ!<!86GJMML)m7KGM|pjc;Z=q=8Qx|1l;NwZ%I}Zz`Xs}v
z3~w^L%kU|~S69tHALaE)hF2NhWO(2G`+xlGKIC(6vcBE!r~QBT^V5vUApbS9nt%91
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKw!SW4}S=h3CyotEP=os3Y0Y$K83)~9oBv}34!?n!~z5g1?E>SmO$VR1q#~>
zA4A{{Yd@QWz<dEh0Rn{r^D7riAaI8Qh3$opA#jJapG`twzCaoZP7lZD`RiF_iI<Ok
znjhxeh`=gE%t{al1YQoa|9&etjk!+R<HO7N=Jm&(KTb)Gm~k5d*RKtvc;^Do6|Mby
z)u36kvZy(p*3D5xkslr^9HXsZ@)80Sg~=iam;yCzea#T{{B34We{<TnP9OTGt~vLG
z<MU~u+{)B7D*<W!4S|}N`BM|;bk66Gn!Apt4e~)>^>ydIR6$NRgsJrfu3HO8?Jo$_
zHTBhk=Eu+Cn0cx>x?jI&Ij6aPz*}LB>lZX@{ObaBG4r%i(3Ft5IA-3!k$F>zo*!0d
z;jCh9fxq6q+5Ytf>SE^4Izh7unM-5l=~pkA2L(b$bM1Jy#`=N+VibW@1S(_Z&l(qA
zj%}l;*o?3--Nf0<W*a!885YZ}j91hy7D2!isEwH`1kGcYwwXQs&9FhPbe2F*XwKYc
zE}e(vawFq&O7Lbr`(pmBkxeUs!>t^-sT+E*vYvVGdEHAM)iLwuXW@y&bI4qJY<^T_
ze_<vkG;btKPO|X}6=8Xj-zV#Dg#hqjt^a3w==Nd!EzZjE<6Bw1%=`ZSP*?t9<=l90
z{~&8Tyr}D(TVM-f=CZ@{L!a{89Lwj!Rzb`RH5iWsDr(p7FJhnOS=d);HqX3Xc{)r4
z_CNVhw75t5(5yR2pqcR#W#gQuLsY&qCfm)}KS<=9Y~TEeK61@S`}|Sass-_CtQPb0
zOw62LTFaL>?f3f!`IG&%^a8$RY`?FsJzjoJl3bUXq$kNW3GSPwH1n^bcHO`t=4qa3
zH?StRFDBxCx=M?DY4kCJx4QBLG4s69Qi&eEkLt>&8=jrAL`>P{O?_98O)Gd~44E98
zyUf4+fs-8AG{-gJX(5@Azn8<ucN5B1%%KF!KDFtARFmAxi=;OzxuDK%XtcedB!{~E
zPLc22s@wTdKh`STX$e&TTOD3Ctl8n-+^*owrjmWA>o3^`OC(4nGg=!o!><~a<TCn9
zn41NC-Ds@~C)4wp-?JZo(k&qUxT;Ro>1ZZ+G<z?hX)u0jj%C88(Z<Ryel=&@o5`2s
z_ewoZNljK67DS(16EB;;Hsz1<^ul#*XWV`aL=@C!Z<f9G_&Xw2gqRf7?0m=qzZ5f@
z3SJ*JEs>z<<VNd)W*9Q>xSuI?duZ}=Mw-gk#)gBOB7Z3FS4nL*lG)9_u)nvDVY)mX
z<VxoA^WkIZV@gi@?}Ob2+m5E}7TWX*!)8rGzJX<|Sn?AcJkQQ<caLALNyj&$SP{Z5
zuY!zO+o|>g*Xd`Tx81LD>LyqsIn{9fetN=KO(UK;37PjDGp!(I#5ai!<GU}?k1GmD
zO%GvQEE<!y=JhjA4^9X>7pvs8iDUBey`VCkzNh`mxXz5z(&IcFoAiz)>5a>6YRo=u
zr$&?V?Xv>a&riH^t57!{GbNDKJb2d<31ees{PeSrjoq?)nU<OR`Sb%}W^VY{e919X
z8}Yis(e{Y+rJx@dA5}$gvts7{drrAFaZJLPJbt;ZKFv!_!haX03!-#nu$f8IG42Y^
z+p6GNLfDYb<H;2!D<|8JnKe<<5>Z5zS#zKF8=v=^SK#fZ!(7~H%p6sQe%!(9SFIN_
zPx{SqW2VxvCY#dvtBIO(BW9a;6Q(6fdnRc{w=u`OOmkYa4d$wUlJ;aph<k{c5;ec)
z9V}ZSVQ4bO=LOBEm$~@+=1CbZs!t0Rj`szNZ~71N(gmd5i+zZ`R?L*+<RI<x(dIgh
zM9sNXYF_;bvLop|?+(+Wmbjh<AK%od-5H$M#-|%@Ujf=DVbChh<ipdX{3)yO)JnMO
z`OKlR%&YO1$gs-HNWbiyO8?yM<@zO?75lKsC&K*viI~|4_yK99nE9}vMap?tiDF^#
zhGnIVS9EEE`XIMIJ)2$4;IrErwW7(Q2iV$IfYS3xR$<;t%>4P8^Lt{Jh*rhbc@M>Q
zUC5lQq@pT^%m0~}DNYh0tZvmRF>_fA>n=jg=xWwnLkw$7bI)l1E!?nL^yA@YH#KhG
zqFLPF(rq?_u~LPs2(cg=UB;};T(O_|BO6(MaAk?~_0E4S4Vp^Gq@S5qYimw&ZeuJR
zrNW16D!K-=<hxzx#H1k^nH;m*jLpA-7;aHNe#qYu(0^oeul6ByeNW+~i4WO7<?534
z@w<tc4M_3fvL%w0P2VW{i6AXx5;JEu=X^X`A!aV^_VwG6&*Y@;)ZO0OCo;a~lN&#?
zwK4NjO>%X+c<ap7CN~<%YOM%yS245ryWp0{q<T9O$_^?mM)i0j{g^u^%uD?q*G*>L
z2QGOHXp)m`fLI<gi+8n?3~3YgS;lh#uF$DHr=2y?^0tk6=G6|TsPkKBcVD%;<*f*D
zUoo@v`IeSQ7@FMif}W-tGU;dLD|qIe+%;9FA^FGV1!b7Yk}}&rsk!XISkok@-;)??
z>-1Bbn#!MWkj+c4)s$_UeY3o_Rx3i>S<IA^nk9;s$XN4A#@yuekV(ueDW>UXGT~@x
z%q%@CJ<UvZDwE5xF1a-(yK3c);n{-Y`kOK3lUtdUX)oRO)gGK%7hQhT3S>oyyNj98
zvqSZ&Vu?&^pF5@Pq=H0qRUr6C>1dc0^Vqz(#d@v3{mDLZz1p$)ZkLHhYLy>N-F_x9
zbHuuVG4n9G^5I720l(hMvLeJC#ms&)3wB2RN5e2wJ8lNe?zS)`xr*8uX3&b6*|S{X
z3TBL(2a{KfnLGVN{=%4P?-DAC$-Hq=u2U{<ag#jhJCeyqHa21Q3C+fq-OyaerE3K0
z-91W^9h%JI60|l^&5a%Ohm0*4@sEBik=Y3w<(R*dHe0^=H^Ph^@*m5DmT>90<7zo}
zIk;xb)Vqw!V&*!x{e-2FiiF&2T{9n2R73Re?gmH9bC25P8h;zj=B{_KtVQlIX6n7|
zkk%3jYk1jsHfS2R9f!Fo91k;N^fUFy5-vP@+}H`F5hANmxS7VsRL?~*bN!Gh_qSW!
z2!qntaN{jCHRJO)|CV`huH6>oZjl*<fAsE$6(R02W|~Kn4Y4IMJECMS=VeaNw+Xlf
zoqiz9m=!Zu-Z)9tXy|E^y<p5#cLz&i=6bjNgvFJ+nk|x*C*;Dl$KzTpi$AleY5f$;
zx%L}XF}so0J}mcGPOA~!R?Ivd(?9uzHu+hUd5_!jj({wYFf<j8>oHoZ%)<(^1)P6l
zSXM@in7K3W)(BTpJZ@CftHw<AGSHHkX>3@&9Q=3G{&1^Zx<ir2lQd8MXp-vwH4;@~
zjPdE)f6F|1=aja#b>{kVw=Y={;<jR@er}<GXn%yIJQ}1ADw$|nBE^v;_@LHb$=y%b
zEjGzc*+h_@TuI3O=~o59h3Af+jL>r3n5lI%omQkR(gR%L$h<8}C5*Lc7F__62XZz)
z)Fyw;Zv+|VlF!vfsc2;t>Q+Bx_6wVzn49_67q|ABt36hP*h<W7%2)QiAEjZ_Xy&pe
zOGJ}(=cPf@I6!OGR#9KwOkC^(2Ih5RrgnWRSL@HhM$AkLt)f)aMU*hs7EVDo^EvwY
zih>7rr4d@q)MjSpE_1KmYNbqaRohByOEI%4^s;CB3x;*{x^m2HeB-kLPRJx?*0o^e
zd`ErE%(a)gtWB2EJNy3GOu4nT4X)uo?lYIt2tCQm<|gc`Kq1ZI@ob6QQ_Pg8={~u;
zl{A}@B{HuZ+BLO7b8-;nh0MPjGhgKVbo6&@&fQ7NF4%u7&B-iiS!o)C&L!-ezZpY~
zoEJJaS(bdZ*(}JX{?mePkj~s%>mAZ32eV_|H#wGU&%8D{<I~xbfmVblDSy-5+P+B`
z>DOYNlFe>Hzi|8de6$kn#jFZyiS*0QeGN~JW$J#g%E<<mO$19{dDNhseQd7X_|crZ
zEBxi<wB)N}X2F576pS3$4A&neo9%B>7Bm{AL!2CoB*mVsHqKY#liPrkHE(N%R!1&V
z<@FnlM9Yd01;uZBr<Hizx(mfjsmS`V&zN#Erl#I)j3qK%$&9J-iDKEhKd#M2Ro@*K
zzV_IqV`jHK1!wN$3zW&W*T&4EZl?0fJMznvYVkxfm3HBE7maFTlz^n09Gpja+1zCI
z*dQtWWi#@1z={ytjG6M3YN?afc8R6YX?2!t3*t2M>fFOa-y2B#UTMizRO56d*P3Ir
z*mPT+?wi$z(C^urP$gX|{Sgb}GTCEuC!ft4w6lw1UKHGwj;51hN;#Hqe7bzxzIH4Q
z(9zqQn@snNBgL9y`4X`r#8zWw$wRU8{Q*nlTqe>mX8)b*rWF?Y60fMn{i4@@y;jWh
zk6w3aD5~sd=DQd}(d7Gm`+Q>?mX70?yK!cqFp5A@jIW#znb_!va@zV5wce;YR)pAW
z%q$3+`HrR~(icuav&huQv@g`Jb9~J#YRw)OzV?{WVAIZ#<7V$rvez+tnB*|Dwx8)_
zQ_?ejJEG({t;y*lqlGqGmu^{D%r?w1s?fdGW?z#XPH3^(xKXbo&`FZpjhXiMdfSc6
zp3$^KdLF+~<!YqaVK}cox2!S0&)D@}jk>jR%(PCZv@~gCaY9k%*xZgmO;Tx(HiY+2
zBP0pucj4`p#eKyvH5tzzG|AGjO1r`>|5MWKh=3|4v+>~`uK{({!M&j;+tx1|GfN7*
zqC!_xij@}0I?5@(q(|WFYwUie`-SZEsI4w$IswcJnF8x<XL`VFFA#^lxaiEK<M>=r
zyKZcek`@{h&7HRDfR+A+`<dzPHAc%eCrhMXiCIa_8b-`Cc!-%g4l#4$;`F-vM!M+r
zI7x9jVMT~d$4uqUlPO{@?pY%J8gk1{ZM7+4rlxY9=fuqHm)XvX$2}^!ifvcnbb+>j
zt@hF+mG+<edeOhSNB8l;y?J!)R%JWGQE&f@wc!`*F7Cbr7QUV=9xFoF70z1g`Ms#L
zCflK&FR(PM-m;n(XLpo)M5!gxZvip0m$2ek8e1GUFJ?MbV5MVoC(xz`)`P`3Vw|yP
z>uMCOofvDiBS~}K(rR1T)=bA^EQabav;3?GvGJIhHlZn@8nx{+y!{HCwr|wH8|-JE
z9=^-|)T(OKuGM3va}Q8@2<wEuC~}=k*NM!|1)%dv?5<xNckO)Y+3f40+nbL14o2nN
z%3CEDQb(SOF}pnKW2QX0^1HuNJA<t@vhyaW5o^_crgun_Y3-Is&wp1jGvkn!X&RHn
z!&rLtm}yt#<O;DHP4r;og*&TO_Z7sw#y{P6+B*Z)eMrgtf<{w__ZKt0-cVpuH)`)T
ztq5WEGrL%CuiUC#SBRO;6LvEP=axuc0(TWNi#JBCs@IH}c4*n9dt4{Tsxi|!(p4gJ
zUn|1bd288!91rb-gw-ZDjjv%U?YNgz)GJH(h1;9+;C;_8L7F#14Ne1-6(Q6DJTKXw
z#5S7DPJe*QIrnO|(po=ms~w()4GKq`%BF9hCDP}nILw5(X~&%`wFx8(`7`>A)w~vO
zjN0EZD!}UfOs5J&!9gr)Vy2Tw+-=K=8!l~eCjE)#VI=##d?{BB-{d(-K@5#LigAiw
zO3~teWxD-O9AblYr!&2&-o=U#dQ54T9GZ`L|87z*f=#<d%yc@M`azf_(&xW8%=FB|
zD=~ARNJqS;;6#TgI7ngD#7rj<wQt(ji{RDi6Z@fejG^{ZDV+0T_jqi+a~gI~3{|5}
z^R^;HK4u0L$2v0j^_ZFVJVHagbyy<((hh1G4Td?_ikYX9&FD6#cw>egWzW#O>WJ<3
zuHMhocXESmTHR`5ro-XI^}*&a<Vzi~tLCs4cf@-jQgXDX=4NX%*V0pYomx}*EV!_C
z8bLGsSe(17^fT2na6?Y?E_g|>aoUwp1Fsb`hmCYc%p--#mi%_ibi#v@J*V~uyZ(X6
zc}kGqKkV1!)RE%Y+pkZ3t#}~Fq)4|qp_KLLQ}EO=vymI!fY!@eINQ&h{?>fHD*t-S
zG|#AJo}y`q^yT8T2csrlFJ{UuMA0+P^~qzlnB&b*E2>e!R_<qdKhdM~J!)d6!(r9w
zzIwE;222C1Vop}zPwc<dp2xJ@;vK{E-K|bp#juxO<#hhcM(&|n3+HN2{8W}~?XWgX
z&DhG<faFn{X2nwvpVG5p={jydW<Gr6O0T|^sLecE_}cen95=J?<@JZt2winP(>V_r
zN1(KB^mA5QQNP0I_4H7-w~I@yzWi@#NvmNSN51Dx=&xW$q}`-<5wPaiym=1RG}Pvr
z!tcjS``}#7_j5teR2M9&QdU{_C0Mkg>4*A7yVujt1tMmqYjmxc>4i+S<5tnnbXrUt
zfu```l-F{t#u2VZ9WVX452+<__j_7#wmM}tY@<$g+iTjZJ*m)X8vLf^qxV#jr>&lT
zaz{;8)~?gfv=7ep_MvrHrZE0<YeM45_;q5YbFpNSqsfGMNE07lv?xaXOd*|pO}?Lb
zdQj_2n0IYgR}nLvES8ktxw1HIPs?vq&Gbn*>2lDUX2>y&$LS1jY<nc$tkBB*wzzDz
z8F2Nh93j^1n3*;N$!%tzdIK>t-phuxKN+56uP|AtnQ$6b2po-<w7F=JlF4ZfYqKZ6
zpKbi<m*OuTGv%(u?+-U(>fdOrh?&mr#%ik5LhveySu>+m4U-ZtkG@4%W0I2z;hP&C
zw@%~P4-`$i-UDwl;y0ezF;lNJdN<$(VrIVUB0RbMksCC9*IaG9M$FW^&$%20^WBGz
zPAXS7v1ZInf2;R+kbApJI#uefyypJQ^?HYfOk+MfX14o|5{sZjl@ltHcQ-s?+_idg
z=#53aD${_?jhVTUR`0C6ftYD_!?Qm>=>^T3j+vQGe?jxGW2RnJjOv-jF~^OVsqB=7
zS;Wjq70yMX#w*tu>Q-QOQH}cCC$BezuAG#8TK<BQ)*NmiW|}*NY|Px*(W9XM-uuR{
zSLkQv@BNB16Hhx^J+$6%#HeGlV`iM68PodV&-`O^Z---5>5xUn4Vh-cN@~Km#^$1r
z(jI-G1jb)v8=o+HL*^Nlgk)sSon@Sm%!`>;qf)YIRWS9ejI{@-JmR$SV4U}`ua9aw
zhzV<UqNJr{7tX&Cl)Bee^DFW86k#I6xDgrV#!Te`l#$uVTSvVf|7y&1D(qn(^hRc0
z^qIh<^?363mM5&1ZP}Z_)>^Q~((77RiphR0Z3IDaD_@|nw(43j)7q*0C~>}rX?oOI
zoSTlB^_jDFi9tzEMpulPJ^lRG+~H3}%uFi%G&fe2p18P=Xe*7G`&n1Xr@2kOY%W=h
zKe5?q3(zWf>!99>2m@3$EQoGWea!gtvrodHRl$-EH(9zsKhqSl!b_&>(l!ihxq((4
zxk5kF*b%5%8fR`bX68bscS1k8rYyV3q|%Q(GNvpMMapr~xv4$v0gj6fV{%AtXK0eU
zbV5la{m@qDSeJ5)7HTbKp9noe&54<2_>p2xPNdy@%rrVla>6NZW0Z(f0g0IoP{rHo
zeWPvInI8e2KzH4kS@hjV6HMvln4jO&n^ru^A7fknva$;m`M8kuGmRK>-Y>=>=oVt8
z)q{6V{pB~9m^t)>;xZ3fU3w~~-Yr;dH2R{%g+6!d$4sle^r@a-oy3(c;B*E1WnIjM
zN$Y?|d>fuLqn~;l+ia{+UA&`=vz1i`rbh*C8B2*rZQ>SUrU`2__{JyOfr+;BY+3R`
zKeI%s{4>uV=AqWK3dgHedW}v$v!oI9k#AYdTp?oWKad$CY<Sv=FS#aaUIB9A!I`Q!
zW;XT9`fyiM4wDkFwn^O&SOG5I+n%HuPgtvT`kDFrj&lVPC!S6dGgFiLId;UXIXij1
zm}xfNQ^^yHJU9Kx3Eom0df#eHneX`7w|J>RDFLy<;AAIl#lL>fDwTASs<q7IgMGHF
z0QVa)Q@*UB0ueKZA~$x;7d|$Be)+H}Sd&Ait9Rjkrdq}Os&0PiS^rwyuxQzc9y0Ie
zy1Dbc@oD#MAhW7WVTe&f!nr|&Wp14X7}}4FO!m`O{=$_H8+3CqGxH5MV&+ihzZ5f{
zU%nr#y4&S%e#~^1Sn=3A-_Ja$U#c4#N#RH)WZqNEG|x@y71J!h!e(vNyP%(GU7{MA
zPdgIE>N|*;da)GZDz)1>oaiBy#k^VlqRs1F-)kiIy^DqPFs+I^XgCp2>1R$4loIxQ
zpc~R0Mkd{dWKHU`>)K`a^#vHDl6LaX84EtM`BAHnrI)?c_tTe1k*umWb_KQTZ$sUP
zMuPZ$4>3~>n#9bZ(1YTRYggKA>)nQRKffI0G2AcHp9&aq6OA~n;3i{cdYkjG?K4L5
zPfVDxlH32NbpcR2I5+osMpd3jSTS?xXPO<_sG5cs&u<}S9+Lb8Gm4ayT~mGA|5N?U
zq(;}f1(o)>{Uz|CuIBnNGufn|HbtZ15m%7?el*jl)(M%%d_Md1@8Z=u{?!`yQNKRX
zmYj2lF?yB6%(lN^eQ;V?#xGIcLd-OSR8bpNP7D<-HzEgPW_Hew!N*HS!xE@Jv|IUm
zKxtH{cbh_VVbi?LsA~qpZhyM`d1`(?(|(3^SPJfUCsUnf@v-r!IWC)N_QK0nv5`+b
zPst}!+78o-NX|ZP6tO~Ke{60gG|A<8V%Sw$3-&7?vm#^G`HA99nyfK%5$BxKvNoIs
z&9ddD8R@3}Qp`+mZ>@KWEt{yhd-jgdwPq8nNr{=pV_Vt<ttuV01*gIuqK~(eYlO__
z)ICfp*#0{hwaO#yJXrC?EBO)2ikat~v|R*YarEQ;mnf|bx>n3oj;#A^{**E$C+6zg
z{vV2&iCTEtW~_mAW5mp?+n<V=>YnG^z|)<U6%2AWbf(UJ%*=m-aEv|UShv3Osf1gI
znN}Y1&(DmY;^u#^G1J771IMwPhcWG}QKzR=(0aG1K$^+s3VQQ<e#T!#KQrx|Op;bM
zDwlp<rd^}f+T9<Do8(2Ecs@9Vs4lhLnMMUjPEeXxfXeHp)(rYe&~^p&(=Po-a<5$m
ztkSzyKhrQxzEPjAIZ@Co_l;M1)BQ}jhbRB{{r#W?&1_`Q_O<nHv12<eLDN13TM;vz
zELs;GqQ;Pw>9$2%Q-6S_Zf(iTXa6RwlGSYJGuBQlE=#NNIaMVTv0`R(Y_6U1iRy+n
z+5Hmb4a7`y*D}Lt>JS%3C~A*e#nwaGYf#_q7j0gho|3wJ(M)ysnTrhS8J#+}^Eo0t
zkNKNwgu*G{X`yz8x$QZpUQ&MDio9}A8hg?)(l<Ff_r<>|c1O?8>=>+5l<~p26_1>9
z56!KZ*>nZ1WX^R%eQB=)SqopOpJ|cies?nT8OA4Vv##wo>ndq;Lz?9yVHsR3W~%!i
zy{@H~&DtC~Zik2H@B91X=>4RF)zhqqnQ=Rd%0S(3g!;p{7XX#U;qXLRi6)<q-W9Pf
zYtdqxpHv)&GMEM#tL(he3Ynaksq74g3|S+mpXMvG<(qTPk`>{c${cP~Fs>Z|4H=)c
z$}niwSMJ}And$FG1X#|f8Z#f{4)f^m<@lXBBjUInhLQ<J+{f-3U%04<na;O&w61B8
z*<jRLQQA11C9KkUIX+~_gB*3E)@ru+p4FnJJ9I0U%?Slo%zU<Q)JaNXIz!IQq}5{l
z$aEKQF0A!qrj>>G(REIZ39dIdZQodtRl+@vv3TySe$nRD>Srn(<+r!w_S04!3Nz+j
zH&<h(tiky<p?VsiO}HXvdL0f$aJr5Cl+y~89niFe=ZZR=UvztapRK$4zIkJzKn~kF
zy%uimRjfu6i(B>m+1P^**~*W6-$Kl^wy*S7quy-f*lNsFdr8F`lZ%=8DiFWpB$bPq
zKlb(H=mK4kXhqEQDusFA5+v>IkW<X^omXEW<yHFhWnaA?vKB0SAEQ?H@epjH)m@ne
z*I*%S)QBmkpkp<NmyL95JzD$Z>-00Tt+3e+r$wb)L(p{Ee!Ao^$11qqcKC4lNWW<F
zYV0z%8Z)D348|_UTrGA=xP~K*b)o$@?nS_~X3o86{yaZkHrb2uHa~40oQ7R@D;mve
z(7D>y=vwbJ?|XkIYX#SdnbtnY`Q>=6F7=Ib7V%_7#LNlDbRvx-Llv`+baTz2CT51s
zY?{4pDwo!f)o#Q)IhpoX=Txf7c-dr4+oo;LGmg1~3SfoS;9~_8R#=N_K|FbKANd+D
z5l&wxW}2JlwGM^veCljY^`5SUm^t;BOc^oLKFyd0psuPpZ9(m4+R-`x?EbKF%eYrX
zlF;jQOb4k2@v_O|u%5da$(4Sywd29L^{IK0zzix)qWWL6*hl^mfcip{xmSsq5}}L@
zG!A03^{ES*UW3Rk{>%3osX?N6V@eN8C*?euaFQ}&ru{P{xt!I+OglQ;*Br);_12Q+
z*ju8lQw!r|lfQi3-0C~lRiJSXXas`d?*n#1)|$o|pp7-L*{bB)GQqs7#LQ%89%Nwt
z>C9HF-Ca3t->7^N#oa$+@!VVCI*na{8Z-Cl-9pjLL*3+}yC}L0I&M~V8Y{nMkSXYz
znCbQq&GS8dL3llvv>tc|^AfG+T_EqX61{4C8=sdc{bs|58c<)i5}fLo+0|jI!yA=V
zG<l7fX`RB5J6IBoq8ZI5J8j=sPuf-@7nw8`&%G6{WNyq1m%Z?~<5pj<Gxcz2F}j<&
z3;D65v-fq)PH=d%m!7cpi?Lp^yW`9Y<e9R}<!Hn6t$Nc}xhAgWf}PP~G?m<HGT_7P
zey>=x(;b!yMy?Svjs1`0q}S9~ta;KtYZv|P?*ZvSA}Ey$k2-Ev-R~=$UNY&SZo4H_
zG1EOr?ym&qvAVAg>sf8*Dh1)h%<wA}lY~$EQ}Z{OXH6Kn+U#4#)}L9e<M-3d?KV=g
z;KzDp$EEx_t`IY&30j+{=AeY{o0yp|SM!|(G1CqyYsO5!blr}EcVw<z39y&Re?#;^
ze(B@o<#0I4<5lE2Di05PJBXIl@U4BuDv++3XAVT#+UnHG1j7m{+3J4^E=MVQ%<OXE
z8*0R|4yNr!lWbW3c#-S|&R*Y`#P?j~anWOFkQpC8T|5@9$vD!eEv#_$OU4~HtDk8X
z7cuis$4o13bal?SAL++@28_}KvmwQ78e!efR9AC(dGqoy)7tq+2EuJnV60i~Zy#D8
z$iGL-%-fik6z!OqIrOSJHg`{G?y|?p=SuJYJh{^CG5eYMuR2LR9<JCmwC#j+JYTvX
znznDlf4grPN4xE13u|v|!fPa{sTb_z{b?#ze)223c+7ON<uoVFYK?isOheHsvT2=*
zSCZ*KJB6HEO0An=l6KJaL#CFnxq<m=)0`z6f@X7+{u0~<p`8N=x8rWcm3`0<dYaO-
z`cH?s3N<k^{*srK;UVYoh*~eLKDOP_NVYqF0;tQ0Sw)kztu`ZH`A49N#Kwi^e|Ium
z_QK;%-`<Fs-W}h1N24xg794^Y{l1@X|5#6JF=qYFw|V8-*cd{!o_j^@y8T5m#~E#P
zmX>b4ZMv&lUJ*0XQp%TTz71YDW?GfH&6JwHO0?=sVy3}q#LRd<9j|58nCXPtChhFc
zx19<?rdm18wySSmQ<3d`zY?5dx%-$lLXcb*R~UxKWSsub(9DmS<0bQPmH8qavKEi1
zF>AGcrdlh*ESNQP+_2Thh?xdyK4yB|%*-RSoZzP&BDa;q=?}M?aL{g-JbkP6I@)G+
zJJYU6uvE5zX{|9>P6;K!yLU8dMUKNRe+B5|R1uA6cFa_7J$u>DUXNP0tSz4t<=l{|
zUxLzrR-Q-9G(go@(gZR4S#Zr7^`PQ3h-}O><5#-@avAVBxygM0P<C!i&8(SMCH8ea
z06V&C8)*1%`K^3d{Q0&nQ``M?Rb+Oo(+kPURadz2zn6@e_9^-%CvyU@>Q+0Gm}$u6
zV&;Q;{G<g3DP}Vc$pLn@q3N|e%(`4|ksBjF<aWsRmh#j7;rrm9$ZXe;X)IQ}9iBoM
zH6tguYbk{raYy6E;rB`1M|F};KV1cy88fqIYx2*^j!L<oykN{UpWE4{Un3Rr$yxT`
z>g0IN-5)cGwwK|%lY>Mv;{LWpQ!rX^XqL63SUzStv8b&Jayw6Zjk<l6>JU~CYdm)l
zWcGOUX77DPQ>$%O);9cJrUp!^k}^@#d72qB^QYpoM-NIyn^_l&na>5`+pL~`#d&VN
zZZZE)mdgE5&IHNNK=O%jd81R74-(-DE;sIU-(F%<`3<#$T2W$vOpB?Gna-t^bMnvf
z^_%mpJ#mJNX)Ta7<Yt^!51sZ_*R;uj7HN%~ZTc;3Tm72s32G$sVy3lUn;A6Krm*~c
zrkrH*p`50qIfe5wKdR`bTlk4Et-|qe&DV{Yr|;}vdXdD5nS~pxd@K`(oPsuXA?`(|
zb0)eY3nfR{S=pQ5?1P_lG5>m#x+lqIY~yc~ob?KuNjqNkoSs=R)2v9jLyjb$-HeOG
z%;$ssd!@3q%?2-Px|a@_+d4Kky6kC<u;G(48|AGyv!kq!nLqg>s`6Z^pUn3yY@L^B
z)js(rdG%Xt)J)yO%vquA9F=VHj7o7rO}MdBQ1@z?h<TA?^YlWdo_ftWjDRm+>GkAh
z&kfQl9SzgCZa;Iym|429>F07)Z$Zo~J33FZ;>|H0iew&~%a?t|D^B}|5ASE+B_HWN
ztEnbl1~>bDMZ0wBM~0#}W{S4aJleGz)gf%t-T2D=Ou39%bgobmw~v7`PUGx~qDi;j
zoHM3XJQl9cj+t``JY1_X-mc216lt5ace=$}n|v^HXkLE}NVZnJsV+%*?u_&hJAgHL
z+6(pVGmJ{FH|a;Kb920z&s!(<0_1SisJzBz&uBt^_bgX+!)*5BtHn$?qI)@fr0351
zgpyYyrWjEDTXVKCNxE!CpVW-kaK+a43Db-c57(L-H&VM=%uEwH=ho>*80Rx(1?HKk
z8D$fGRK1il&^jH>;fhnZ#{76jCBMMd-^rYy8F<qXH3+#3<t@lA&@Q1FeK0k<)~@1o
zjQ`|;f$bv$=iN|Ww{PhouMje8j-JBmU_`N^pCby_<%~-NHg2&=8?D)q>WSyS>K!V{
zyOldh#*Udk))mkBnQWFwMW(=>PkY9<H0exLEnR$jpUZ6UlsKI7dx0uKam*|`qAd^g
zvtwqsvAJ>C8gGLtoz8f(izSy+Yra}g_RMf~R?K|<$lk^suA+F{e1uOLA-tGiZ)EP>
zG@U;G%VOs0*MZ!thh>c{=P;e0Q<;A1o~EoPar8A}@@lmd1I7z6LmCHTCF5Jpo_knZ
z#WkQ{*#)B|z2$Lp;<2lQ%uDt&WrNzsg{}0D(aDsQ(pF2%w5u*LGj4ISre_@HHsw%t
zqmg8&G-j68_S_ZBq^?|~pP8f*&sbI|uM;va95ZLt!bKmxR?N&7%ff!<+8s^5O|N)|
zQ!cSZMS9x{=e~OzM}hNnX-tbZx*%pYA1OZxSeoxE#>{aWmxaviX|qh3)Xt8}s9-uw
zs`7}VAeEUPxl+tDcGF8^=8t*qVJ=55iiL$&-q4)Xvp2Cg%WeAYStp*H%8`c{<4IU@
z@%WsRfcd@tWUW_>nM1k@LuQ%PkXrRfzO=IMglYY;m}y;#cA7=OnI!k?iP<8F-*8W6
zc4b)G`H7Ot??|E#-qmDb?CGSdcTXj8VCFOCN_MBeaz1m}b<pgNJB(MWj8|0SFx|fu
zGt<s&V6i-Au6CQI721OwdtV$WtQ&?(;Tksiu~}Dv)LvW3W*5cGnQJe)c&@I~y4NVI
zSo6lu+qmpF>(H#FL~CB&v`?3mTlAT5HGe8*+P$|GVx|N!`$|_-5}C<E@nNI$ZM)3+
zr?ag9J^kdJO%;WnuCdHHcAhGgM1jL}5qGNKkmncrnFYT&U~F0bSSJiu>x>)O$h{RN
z{Fh>;9Woc*pV^}>+u1fnmi;A+K8eZevYIN%nO`=_RiV3>KjV@^eKRSDne)%ElmwV7
z_cIsv7D~2gQty{cRMg%ux%$dbk+8K$dVn~;Dp~87;NbKt*63#nZBu!cbT$u8Hp9|u
z#uo<ZquHmmMK}I#`N6qUH7o}|X4af4EeQ8ljG0mk_sar_x#Ny&{Nib=yfW{FX)fE;
zOae8tFCH`P;2<VW!zel+YH6Dvttfx0@DwY0AW>LUx$(X1Txx@~_x#vt=I(8(>|%<z
zFW7y%F|+QDG5-SAHDjj#q(QstTsLHLf2Lg;{ksLRXtkL6BUMQHniX-ZAeUO?Y`U5?
z$?e=eZO?a~uccQ+mfS+)#mw4k&3(MjuK$WL^I_px{ItKM)$;Y`Rn+D%@xRf}be@#j
zfvguZrO*0sl#n?yj#WlX$$h(@pPAZDB4)P1^;M*zc5P{q!qXr%N6$TjLtOoA7dOsa
zEoLt5WV$EK`pUT4YhN}qUc<EiK+G(CQtFy9Q;7E;YOT$c(@XNhlwmQs<EP>uWjkk}
zOeL4wJDKkv;kNK{uBH0ViJA3B{r&N5E&;XnmG-RN`Zjz(Dqgisx1byShqTrjsmO4c
z^nJ(7=a=KR-<djltQ<3&&SuHOewzZ62L$J;epp!c_`W=BJ|7F8A6rqowzNpuRiN6h
znzs^mxi0C!$_<Uy%C8bLXYZ=h+Tq;IV%Pb)chgL`bHapfIA(qy7W^IC2mj5AL?<UX
ztAd84;rK}cnf;LTna^_#SDuVZYDYUYsT;B%c`&b)hpTn#(#AhfbZ}nZ7Ze?{*3{qj
z*|^)i<jcp*rgB%Dw4YX)UkI6Zd<`gUyIUSV$uEe?FJi{Et9|<QxBTMyy4!X-b*Uw1
zH=D<8A3vnqJtx6w{l34ck_TQm#~%)grCoddr%$rK4y4wgOUKOp!?&75pSiNv-w2t+
zOtr$?-ptd!`E6nO+073bn$i7!R`i;;MW@qV(rbU@v+HnIrdL++H~c9pq@Br^96y`=
z%q5rOJ94X=tOm4|&Sy3|=H*??W*f|~Kd;W0f4ZW+hAY3}WAiYZ+aD)pR@BtXFJd3x
zw$)AzKE*l9p9WdsH>9k4hShAZ5HnBf1x)Ys!lhb$ap8?0470N6T+O)3<zv^sdKNM;
zt_v(L*Bf7hA4Ha&b2QFpuF>?2uN<l|v*cWaUK3=lL`&K8f2`BNZ0kkA9xI!h1#eW;
z$uPBL2ObrP=N9R2od`3>_-_m3O6z{+%lTdVZ{d-c-p`a%0_(KA{Ff-znE7IFtMRU!
zzWgY?4WzVo{8GqVdOma6&v%sK6nyS_PtW`9IJBko3kq)IACX@*w*MAx--Dc4PXFZi
zcHw&a#Xr*Z%Nz-QYRudn?2XO5n_N)rQ(yG@TOo64%*@a(vZz}4S55|RDSZ7(UaN|d
zg%BtZ_%LrTy<~MS$Xxu9Np{xS-^Gc{oNk{uI>{IlHy|*x6!|y;r2_f03Ky^UrCAI<
zH_g)_c<0wfxdJpTlv|nlwF*JPcP{Xo=i(}8rw#HZj?TXe?vtBlo2hFERMajOLBJRI
z&5*hDe5N$Kg%7RuecVrYPjS3PbRZ2)z%4pHfIx-7@1BaQ$ndmr$T$6e`S5(+k2y?p
z&(uW)Dry&tAm9lYx0PPBI-ghWWlwoO&DKNmZD?h&3(caFnU=@R%(+mRv)Vr`@XH}{
zg=6!kfyyIFKAgw;T;%QJ8V^CcnFw=#8Tr#qn~lGW!0#TIOCzn=tov))Y|(`TDry&t
zAYcnTU!?mrW2JWX)ORn`zF6)338?jlnF#zff%|LPY|(`T{#w&udl66tF4VqQ?fnU;
z^@o`V{5665Yuaqlg#`Xu(_niMPz5g3zF6)338?jlnF#zff%|LPY|(`T{#w&udl5hY
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILC>Quo
DNG4Z*

literal 0
HcmV?d00001

diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
new file mode 100644
index 0000000000..b5eacfc5eb
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
@@ -0,0 +1,9 @@
+// /** @file
+// Platform Logo image definition file.
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+//
+//
+// **/
+
+#image IMG_LOGO S3Logo.bmp
diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
new file mode 100644
index 0000000000..25b46e4bff
--- /dev/null
+++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
@@ -0,0 +1,55 @@
+## @file
+#  The default logo bitmap picture shown on setup screen.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = S3LogoDxe
+  FILE_GUID                      = A3193794-FCBC-E9A4-1AE0-DAEA9A499808
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = InitializeLogo
+#
+#  This flag specifies whether HII resource section is generated into PE image.
+#
+  UEFI_HII_RESOURCE_SECTION      = TRUE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  S3Logo.bmp
+  Logo.c
+  S3Logo.idf
+
+[Packages]
+  AmdPlatformPkg/AmdPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BootLogoLib
+  DebugLib
+  PcdLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiHiiDatabaseProtocolGuid        ## CONSUMES
+  gEfiHiiImageExProtocolGuid         ## CONSUMES
+  gEfiHiiPackageListProtocolGuid     ## PRODUCES CONSUMES
+  gEdkiiPlatformLogoProtocolGuid     ## PRODUCES
+
+[Pcd]
+  gAmdPlatformPkgTokenSpaceGuid.PcdAmdDisplayLogoEventGuid
+
+[Depex]
+  gEfiHiiDatabaseProtocolGuid AND
+  gEfiHiiImageExProtocolGuid
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114577): https://edk2.groups.io/g/devel/message/114577
Mute This Topic: https://groups.io/mt/103975435/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 02/32] AMD/VanGoghBoard: Check in ACPI tables
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:10 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 03/32] AMD/VanGoghBoard: Check in Capsule update Zhai, MingXin (Duke) via groups.io
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:10 UTC (permalink / raw)
  To: devel; +Cc: Duke Zhai, Ken Yao, Igniculus Fu, Abner Chang

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="yes", Size: 366 bytes --]



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114578): https://edk2.groups.io/g/devel/message/114578
Mute This Topic: https://groups.io/mt/103975437/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 03/32] AMD/VanGoghBoard: Check in Capsule update
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 02/32] AMD/VanGoghBoard: Check in ACPI tables Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:10 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 04/32] AMD/VanGoghBoard: Check in AgesaPublicPkg Zhai, MingXin (Duke) via groups.io
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:10 UTC (permalink / raw)
  To: devel; +Cc: Duke Zhai, Eric Xing, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Chachani board supports "Capsule on Disk (CoD)" feature defined in UEFI
  Spec chapter 8.5.5 "Delivery of Capsules via file on Mass Storage Device".
  The BIOS capsule image is saved in hard disk as default setting.

Signed-off-by: Ken Yao <ken.yao@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../SystemFirmwareDescriptor.aslc             |   85 ++
 .../SystemFirmwareDescriptor.inf              |   39 +
 .../SystemFirmwareDescriptorPei.c             |   64 +
 .../Include/Library/CapsuleHookLib.h          |   40 +
 .../Capsule/CapsuleHookLib/CapsuleHookLib.c   | 1153 +++++++++++++++++
 .../Capsule/CapsuleHookLib/CapsuleHookLib.inf |   56 +
 .../PlatformBootManager.c                     |  794 ++++++++++++
 .../PlatformBootManager.h                     |  150 +++
 .../PlatformBootManagerLib.inf                |   89 ++
 .../PlatformBootManagerLib/PlatformConsole.c  |  495 +++++++
 .../PlatformBootManagerLib/PlatformConsole.h  |   69 +
 .../PlatformBootManagerLib/PlatformData.c     |   39 +
 .../CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf   |  115 ++
 .../CapsuleRuntimeDxe/CapsuleService.c        |  461 +++++++
 .../CapsuleRuntimeDxe/CapsuleService.h        |   73 ++
 15 files changed, 3722 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.aslc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptorPei.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/CapsuleHookLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManagerLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformData.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h

diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.aslc b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.aslc
new file mode 100644
index 0000000000..2e05a523c7
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.aslc
@@ -0,0 +1,85 @@
+/** @file
+  System firmware Descriptor file
+  System Firmware descriptor.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#define PACKAGE_VERSION                     0xFFFFFFFF
+#define PACKAGE_VERSION_STRING              L"Unknown"
+
+#define CURRENT_FIRMWARE_VERSION            0x00003818
+#define CURRENT_FIRMWARE_VERSION_STRING     L"00003818"
+#define LOWEST_SUPPORTED_FIRMWARE_VERSION   0x00000001
+
+#define IMAGE_ID                            SIGNATURE_64('C', 'H', 'A', 'C', 'H', 'A','N','I')
+#define IMAGE_ID_STRING                     L"ChachaniFD"
+
+// PcdSystemFmpCapsuleImageTypeIdGuid
+#define IMAGE_TYPE_ID_GUID                  { 0x38663fe6, 0x934f, 0x42a1, { 0xbc, 0xb0, 0xf7, 0x9e, 0x62, 0xec, 0xbe, 0x80 } }
+
+typedef struct {
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  Descriptor;
+  // real string data
+  CHAR16                                  ImageIdNameStr[sizeof(IMAGE_ID_STRING)/sizeof(CHAR16)];
+  CHAR16                                  VersionNameStr[sizeof(CURRENT_FIRMWARE_VERSION_STRING)/sizeof(CHAR16)];
+  CHAR16                                  PackageVersionNameStr[sizeof(PACKAGE_VERSION_STRING)/sizeof(CHAR16)];
+} IMAGE_DESCRIPTOR;
+
+IMAGE_DESCRIPTOR mImageDescriptor =
+{
+  {
+    EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE,
+    sizeof(EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR),
+    sizeof(IMAGE_DESCRIPTOR),
+    PACKAGE_VERSION,                                       // PackageVersion
+    OFFSET_OF (IMAGE_DESCRIPTOR, PackageVersionNameStr),   // PackageVersionName
+    1,                                                     // ImageIndex;
+    {0x0},                                                 // Reserved
+    IMAGE_TYPE_ID_GUID,                                    // ImageTypeId;
+    IMAGE_ID,                                              // ImageId;
+    OFFSET_OF (IMAGE_DESCRIPTOR, ImageIdNameStr),          // ImageIdName;
+    CURRENT_FIRMWARE_VERSION,                              // Version;
+    OFFSET_OF (IMAGE_DESCRIPTOR, VersionNameStr),          // VersionName;
+    {0x0},                                                 // Reserved2
+    FixedPcdGet32(PcdFlashAreaSize),                       // Size;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSupported;
+    IMAGE_ATTRIBUTE_IMAGE_UPDATABLE |
+      IMAGE_ATTRIBUTE_RESET_REQUIRED |
+      IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED |
+      IMAGE_ATTRIBUTE_IN_USE,                              // AttributesSetting;
+    0x0,                                                   // Compatibilities;
+    LOWEST_SUPPORTED_FIRMWARE_VERSION,                     // LowestSupportedImageVersion;
+    0x00000000,                                            // LastAttemptVersion;
+    0,                                                     // LastAttemptStatus;
+    {0x0},                                                 // Reserved3
+    0,                                                     // HardwareInstance;
+  },
+  // real string data
+  {IMAGE_ID_STRING},
+  {CURRENT_FIRMWARE_VERSION_STRING},
+  {PACKAGE_VERSION_STRING},
+};
+
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from
+  // removing the data structure from the executable
+  //
+  return (VOID*)&mImageDescriptor;
+}
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.inf b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.inf
new file mode 100644
index 0000000000..50f2b8c1a2
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptor.inf
@@ -0,0 +1,39 @@
+## @file
+#  System Firmware descriptor.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SystemFirmwareDescriptor
+  FILE_GUID                      = 90B2B846-CA6D-4D6E-A8D3-C140A8E110AC
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SystemFirmwareDescriptorPeimEntry
+
+[Sources]
+  SystemFirmwareDescriptorPei.c
+  SystemFirmwareDescriptor.aslc
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SignedCapsulePkg/SignedCapsulePkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  PcdLib
+  PeiServicesLib
+  DebugLib
+  PeimEntryPoint
+
+[Pcd]
+  gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
+
+[Depex]
+  TRUE
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptorPei.c b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptorPei.c
new file mode 100644
index 0000000000..7f0c4421e3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Capsule/SystemFirmwareDescriptor/SystemFirmwareDescriptorPei.c
@@ -0,0 +1,64 @@
+/** @file
+  Implements SystemFirmwareDescriptorPei.c
+  System Firmware descriptor producer.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+/**
+  Entrypoint for SystemFirmwareDescriptor PEIM.
+
+  @param[in]  FileHandle  Handle of the file being invoked.
+  @param[in]  PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS            PPI successfully installed.
+**/
+EFI_STATUS
+EFIAPI
+SystemFirmwareDescriptorPeimEntry (
+  IN EFI_PEI_FILE_HANDLE     FileHandle,
+  IN CONST EFI_PEI_SERVICES  **PeiServices
+  )
+{
+  EFI_STATUS                              Status;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  *Descriptor;
+  UINTN                                   Size;
+  UINTN                                   Index;
+  UINT32                                  AuthenticationStatus;
+
+  //
+  // Search RAW section.
+  //
+  Index = 0;
+  while (TRUE) {
+    Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Index, FileHandle, (VOID **)&Descriptor, &AuthenticationStatus);
+    if (EFI_ERROR (Status)) {
+      // Should not happen, must something wrong in FDF.
+      ASSERT (FALSE);
+      return EFI_NOT_FOUND;
+    }
+
+    if (Descriptor->Signature == EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR_SIGNATURE) {
+      break;
+    }
+
+    Index++;
+  }
+
+  DEBUG ((DEBUG_INFO, "EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR size - 0x%x\n", Descriptor->Length));
+
+  Size = Descriptor->Length;
+  PcdSetPtrS (PcdEdkiiSystemFirmwareImageDescriptor, &Size, Descriptor);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/CapsuleHookLib.h b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/CapsuleHookLib.h
new file mode 100644
index 0000000000..85bad14b52
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Library/CapsuleHookLib.h
@@ -0,0 +1,40 @@
+/** @file
+  Implements CapsuleHookLib.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CAPSULE_HOOK_LIB_H_
+#define CAPSULE_HOOK_LIB_H_
+
+/**
+  Detect Capsule file from ESP partition and update capsule.
+
+  @retval EFI_SUCCESS.              Opertion is successful.
+  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate.
+  @retval EFI_ERROR                 Internal error when update Capsule.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsuleUpdateViaFileHook (
+  VOID
+  );
+
+/**
+  Detect Capsule file from ESP partition and update capsule.
+
+  @retval EFI_SUCCESS.              Opertion is successful.
+  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate.
+  @retval EFI_ERROR                 Internal error when update Capsule.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsuleUpdateViaFileLib (
+  VOID
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.c b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.c
new file mode 100644
index 0000000000..b4513514b8
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.c
@@ -0,0 +1,1153 @@
+/** @file
+  Implements CapsuleHookLib.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <PiDxe.h>
+#include <Guid/Gpt.h>
+#include <Guid/FileSystemInfo.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/BlockIo.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/CapsuleHookLib.h>
+#include <OtaCapsuleUpdate.h>
+
+#define CAP_FILE_NAME  (CHAR16 *) FixedPcdGetPtr (PcdOtaCapsuleName)
+#define CAP_PARTITION  (CHAR16 *) FixedPcdGetPtr (PcdOtaCapsulePartitionName)
+CHAR16                    mPartitionName[36];
+STATIC CONST CHAR16       *mSlotSuffixes[2] = { L"_a", L"_b" };
+EFI_DEVICE_PATH_PROTOCOL  *mBootDevicePath;
+
+#define FLASH_DEVICE_PATH_SIZE(DevPath)  (GetDevicePathSize (DevPath) - sizeof (EFI_DEVICE_PATH_PROTOCOL))
+
+// Hidden (Not exported) function from DxeCapsuleReportLib.
+extern
+EFI_STATUS
+// Not EFIAPI!
+RecordCapsuleStatusVariable (
+  IN EFI_CAPSULE_HEADER  *CapsuleHeader,
+  IN EFI_STATUS          CapsuleStatus
+  );
+
+/**
+  Read GPT partition entries.
+
+  @param[in]  BlockIo             The BlockIo of device.
+  @param[out] PartitionEntries    The output buffer of partition entry.
+
+  @retval EFI_SUCCESS             Operation completed successfully.
+  @retval others                  Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+ReadPartitionEntries (
+  IN EFI_BLOCK_IO_PROTOCOL  *BlockIo,
+  OUT EFI_PARTITION_ENTRY   **PartitionEntries
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       EntrySize;
+  UINTN                       NumEntries;
+  UINTN                       BufferSize;
+  UINT32                      MediaId;
+  EFI_PARTITION_TABLE_HEADER  *GptHeader;
+
+  MediaId = BlockIo->Media->MediaId;
+
+  //
+  // Read size of Partition entry and number of entries from GPT header
+  //
+  GptHeader = AllocatePool (BlockIo->Media->BlockSize);
+  if (GptHeader == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = BlockIo->ReadBlocks (
+                      BlockIo,
+                      MediaId,
+                      PRIMARY_PART_HEADER_LBA,
+                      BlockIo->Media->BlockSize,
+                      (VOID *)GptHeader
+                      );
+  if (EFI_ERROR (Status)) {
+    FreePool (GptHeader);
+    return Status;
+  }
+
+  //
+  // Check there is a GPT on the media
+  //
+  if ((GptHeader->Header.Signature != EFI_PTAB_HEADER_ID) || (GptHeader->MyLBA != PRIMARY_PART_HEADER_LBA)) {
+    DEBUG ((DEBUG_ERROR, "No valid GPT found!\n"));
+    FreePool (GptHeader);
+    return EFI_DEVICE_ERROR;
+  }
+
+  EntrySize  = GptHeader->SizeOfPartitionEntry;
+  NumEntries = GptHeader->NumberOfPartitionEntries;
+  if ((EntrySize == 0) || (NumEntries == 0)) {
+    DEBUG ((DEBUG_ERROR, "Invalid Entry size or number.\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  FreePool (GptHeader);
+
+  BufferSize        = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media->BlockSize);
+  *PartitionEntries = AllocatePool (BufferSize);
+  if (PartitionEntries == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = BlockIo->ReadBlocks (
+                      BlockIo,
+                      MediaId,
+                      2,
+                      BufferSize,
+                      (VOID *)*PartitionEntries
+                      );
+  if (EFI_ERROR (Status)) {
+    FreePool (*PartitionEntries);
+    return Status;
+  }
+
+  return Status;
+}
+
+/**
+  Get capsule partition device path by partition name.
+
+  @param[in]  BootDevicePath      Pointer to the Device Path Protocol from variable.
+  @param[in]  PartitionName       The given partition name.
+  @param[out] PartitionDevicePath Pointer to the Device Path Protocol of capsule partition.
+
+  @retval EFI_SUCCESS             Operation completed successfully.
+  @retval others                  Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDevicePathByName (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *BootDevicePath,
+  IN  CONST CHAR16              *PartitionName,
+  OUT EFI_DEVICE_PATH_PROTOCOL  **PartitionDevicePath
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_BLOCK_IO_PROTOCOL     *BlockIo;
+  EFI_DEVICE_PATH_PROTOCOL  *NextNode;
+  HARDDRIVE_DEVICE_PATH     *PartitionNode;
+  EFI_PARTITION_ENTRY       *PartitionEntries;
+  UINTN                     NumHandles;
+  UINTN                     LoopIndex;
+  EFI_HANDLE                *AllHandles;
+  EFI_HANDLE                Handle;
+
+  //
+  // Get all BlockIo handles in system
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiBlockIoProtocolGuid,
+                  NULL,
+                  &NumHandles,
+                  &AllHandles
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Couldn't locate BlockIo protocol: %r\n", Status));
+    return Status;
+  }
+
+  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
+    Status = gBS->OpenProtocol (
+                    AllHandles[LoopIndex],
+                    &gEfiDevicePathProtocolGuid,
+                    (VOID **)&DevicePath,
+                    gImageHandle,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Couldn't locate DevicePath protocol: %r\n", Status));
+      return Status;
+    }
+
+    if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE (BootDevicePath))) {
+      BootDevicePath = DevicePath;
+      break;
+    }
+  }
+
+  DevicePath = BootDevicePath;
+  Status     = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePath, &Handle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Couldn't locate device status: %r\n", Status));
+    return Status;
+  }
+
+  Status = gBS->OpenProtocol (
+                  Handle,
+                  &gEfiBlockIoProtocolGuid,
+                  (VOID **)&BlockIo,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to get BlockIo: %r\n", Status));
+    return Status;
+  }
+
+  Status = ReadPartitionEntries (BlockIo, &PartitionEntries);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to read partitions from disk device: %r\n", Status));
+    return Status;
+  }
+
+  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
+    Status = gBS->OpenProtocol (
+                    AllHandles[LoopIndex],
+                    &gEfiDevicePathProtocolGuid,
+                    (VOID **)&DevicePath,
+                    gImageHandle,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Couldn't locate DevicePath protocol: %r\n", Status));
+      return Status;
+    }
+
+    if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE (BootDevicePath))) {
+      NextNode = NextDevicePathNode (DevicePath);
+
+      while (!IsDevicePathEndType (NextNode)) {
+        if ((NextNode->Type == MEDIA_DEVICE_PATH) &&
+            (NextNode->SubType == MEDIA_HARDDRIVE_DP))
+        {
+          break;
+        }
+
+        NextNode = NextDevicePathNode (NextNode);
+      }
+
+      if (IsDevicePathEndType (NextNode)) {
+        continue;
+      }
+
+      PartitionNode = (HARDDRIVE_DEVICE_PATH *)NextNode;
+
+      if (PartitionNode->PartitionNumber == 0) {
+        continue;
+      }
+
+      if (0 == StrCmp (PartitionEntries[PartitionNode->PartitionNumber - 1].PartitionName, PartitionName)) {
+        break;
+      }
+    }
+  }
+
+  if (LoopIndex >= NumHandles) {
+    return EFI_LOAD_ERROR;
+  }
+
+  *PartitionDevicePath = DevicePath;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get capsule paritioin information.
+
+  @param[in]  VOID
+
+  @retval EFI_SUCCESS             Operation completed successfully.
+  @retval others                  Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsulePartitionInfo (
+  VOID
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               VarSize;
+  OTA_CAPSULE_UPDATE  OtaCapsuleUpdateVal;
+  CHAR16              BootPath[512];
+
+  //
+  // Get Capsule A/B partition.
+  //
+  ZeroMem (&OtaCapsuleUpdateVal, sizeof (OTA_CAPSULE_UPDATE));
+  VarSize = sizeof (OTA_CAPSULE_UPDATE);
+  Status  = gRT->GetVariable (
+                   OTA_CAPSULE_VAR_NAME,
+                   &gOtaCapsuleUpdateGuid,
+                   NULL,
+                   &VarSize,
+                   (VOID *)&OtaCapsuleUpdateVal
+                   );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CapsulePartitionInfo: GetVariable failed: %r\n", Status));
+    return Status;
+  }
+
+  ZeroMem (mPartitionName, sizeof (mPartitionName));
+  StrCpyS (mPartitionName, sizeof (mPartitionName), CAP_PARTITION);
+  StrCatS (mPartitionName, sizeof (mPartitionName), mSlotSuffixes[OtaCapsuleUpdateVal.UpdateSlot]);
+  DEBUG ((DEBUG_INFO, "CapsulePartitionInfo from partition: %s\n", mPartitionName));
+
+  //
+  // Get Boot device path
+  //
+  VarSize = 512;
+  Status  = gRT->GetVariable (
+                   L"AndroidBootDevice",
+                   &gEfiGlobalVariableGuid,
+                   NULL,
+                   &VarSize,
+                   BootPath
+                   );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CapsulePartitionInfo: Get BootDevice variable failed: %r\n", Status));
+    return Status;
+  }
+
+  mBootDevicePath = ConvertTextToDevicePath (BootPath);
+  if (mBootDevicePath == NULL) {
+    DEBUG ((DEBUG_ERROR, "mBootDevicePath is NULL\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Read Capsule file information from FAT partiton.
+
+  @param[in]  FileName              File name of Capsule binary
+  @param[out] Buffer                Return buffer pointer of Capsule binary
+  @param[out] BufferSize            Capsule binary size
+
+  @retval EFI_SUCCESS               Read Capsule information successfully
+  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate
+  @retval EFI_NOT_FOUND             Fail to read Capsule information
+  @retval Others                    Internal error when read Capsule information
+
+**/
+EFI_STATUS
+EFIAPI
+ReadCapsuleInfo (
+  IN CHAR16  *FileName,
+  OUT VOID   **Buffer,
+  OUT UINTN  *BufferSize
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
+  EFI_FILE                         *Root;
+  EFI_FILE                         *FileHandle;
+  UINT8                            *FileBuffer;
+  UINTN                            FileSize;
+  EFI_HANDLE                       Handle;
+  EFI_BLOCK_IO_PROTOCOL            *BlockIo;
+  EFI_DEVICE_PATH_PROTOCOL         *BootPartitionPath;
+
+  FileBuffer = NULL;
+  FileSize   = 0;
+
+  DEBUG ((DEBUG_INFO, "ReadCapsuleInfo()...\n"));
+
+  Status = GetDevicePathByName (mBootDevicePath, mPartitionName, &BootPartitionPath);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status));
+    return Status;
+  }
+
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BootPartitionPath, &Handle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  //
+  // Get Capsule file
+  //
+  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (BlockIo->Media->RemovableMedia) {
+    return Status;
+  }
+
+  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = Fs->OpenVolume (Fs, &Root);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ, 0);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (FileHandle == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  Status = FileHandleGetSize (FileHandle, (UINT64 *)&FileSize);
+  if (EFI_ERROR (Status)) {
+    FileHandleClose (FileHandle);
+    return Status;
+  }
+
+  FileBuffer = AllocateZeroPool (FileSize);
+  if (FileBuffer == NULL) {
+    FileHandleClose (FileHandle);
+    return Status;
+  }
+
+  Status = FileHandleRead (FileHandle, &FileSize, FileBuffer);
+  if (EFI_ERROR (Status)) {
+    FileHandleClose (FileHandle);
+    FreePool (FileBuffer);
+    return Status;
+  }
+
+  Status = FileHandleClose (FileHandle);
+  if (EFI_ERROR (Status)) {
+    FreePool (FileBuffer);
+    return Status;
+  }
+
+  *Buffer     = FileBuffer;
+  *BufferSize = FileSize;
+
+  DEBUG ((DEBUG_INFO, "Capsule size: 0x%x\n", *BufferSize));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Remove capsule file from FAT partitions.
+
+  @param[in]  FileName              File name of Capsule binary
+
+  @retval EFI_SUCCESS               Delete capsule succesfully
+  @retval Others                    Internal error of delete capsule function
+
+**/
+EFI_STATUS
+EFIAPI
+RemoveCapsuleFile (
+  IN CHAR16  *FileName
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
+  EFI_FILE                         *Root;
+  EFI_FILE                         *FileHandle;
+  EFI_HANDLE                       Handle;
+  EFI_BLOCK_IO_PROTOCOL            *BlockIo;
+  EFI_DEVICE_PATH_PROTOCOL         *BootPartitionPath;
+
+  DEBUG ((DEBUG_INFO, "RemoveCapsuleFile()...\n"));
+
+  Status = GetDevicePathByName (mBootDevicePath, mPartitionName, &BootPartitionPath);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status));
+    return Status;
+  }
+
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BootPartitionPath, &Handle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  //
+  // Remove Capsule file
+  //
+  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (BlockIo->Media->RemovableMedia) {
+    return Status;
+  }
+
+  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = Fs->OpenVolume (Fs, &Root);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = Root->Open (Root, &FileHandle, FileName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (FileHandle == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  Status = FileHandleDelete (FileHandle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Passes and processes the capsule file.
+
+  @param  CapsuleHeaderArray    Virtual pointer to an array of virtual pointers to the capsules
+                                being passed into update capsule.
+  @param  CapsuleCount          Number of pointers to EFI_CAPSULE_HEADER in CaspuleHeaderArray.
+
+  @retval EFI_SUCCESS           Valid capsule was passed.
+  @retval others                Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateCapsule (
+  IN EFI_CAPSULE_HEADER  **CapsuleHeaderArray,
+  IN UINTN               CapsuleCount
+  )
+{
+  UINTN               ArrayNumber;
+  EFI_STATUS          Status;
+  EFI_CAPSULE_HEADER  *CapsuleHeader;
+
+  //
+  // Capsule Count can't be less than one.
+  //
+  if (CapsuleCount < 1) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CapsuleHeader = NULL;
+
+  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+    //
+    // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have
+    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
+    //
+    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must have
+    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
+    //
+    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    // FIXME: The CoD Image CANNOT BE RELOADED as Memory capsule.
+    //
+    // Check FMP capsule flag
+    //
+    if (  CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)
+       && ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0))
+    {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Check Capsule image without populate flag by firmware support capsule function
+    //
+    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
+      Status = SupportCapsuleImage (CapsuleHeader);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+  }
+
+  //
+  // Walk through all capsules, record whether there is a capsule needs reset
+  // or initiate reset. And then process capsules which has no reset flag directly.
+  //
+  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+    //
+    // Here should be in the boot-time for non-reset capsule image
+    // Platform specific update for the non-reset capsule image.
+    //
+
+    // FIXME: The CoD Image CANNOT BE RELOADED as Memory capsule.
+    if (((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) || TRUE) {
+      Status = ProcessCapsuleImage (CapsuleHeader);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Detect Capsule file from ESP partition and update capsule.
+
+  @retval EFI_SUCCESS               Opertion is successful.
+  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate.
+  @retval EFI_ERROR                 Internal error when update Capsule.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsuleUpdateViaFileHook (
+  VOID
+  )
+{
+  EFI_STATUS          Status;
+  UINT8               *CapsuleBuffer;
+  UINTN               CapsuleSize;
+  EFI_CAPSULE_HEADER  *CapsuleHeader;
+  UINTN               CapsuleNum;
+
+  CapsuleBuffer = NULL;
+  CapsuleSize   = 0;
+
+  DEBUG ((DEBUG_INFO, "CapsuleUpdateViaFileHook() Entry Point...\n"));
+
+  Status = CapsulePartitionInfo ();
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CapsulePartitionInfo failed: %r\n", Status));
+    return Status;
+  }
+
+  Status = ReadCapsuleInfo (CAP_FILE_NAME, (VOID **)&CapsuleBuffer, &CapsuleSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Read Capsule file failed. Status: %r\n", Status));
+    if (CapsuleBuffer != NULL) {
+      FreePool (CapsuleBuffer);
+    }
+
+    return Status;
+  }
+
+  CapsuleHeader = (EFI_CAPSULE_HEADER *)CapsuleBuffer;
+  CapsuleNum    = 1;
+
+  Status = UpdateCapsule (&CapsuleHeader, CapsuleNum);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to update capsule. Status: %r\n", Status));
+  }
+
+  if (CapsuleBuffer != NULL) {
+    FreePool (CapsuleBuffer);
+  }
+
+  DEBUG ((DEBUG_INFO, "Capsule update via file completed, reset system...\n"));
+
+  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get capsule partition device path by partition name.
+
+  @param[in]  BootDevicePath      Pointer to the Device Path Protocol from variable.
+  @param[in]  PartitionName       The given partition name.
+  @param[out] PartitionDevicePath Pointer to the Device Path Protocol of capsule partition.
+
+  @retval EFI_SUCCESS             Operation completed successfully.
+  @retval others                  Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+GetDevicePathByBoot (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *BootDevicePath,
+  OUT EFI_DEVICE_PATH_PROTOCOL  **PartitionDevicePath
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_BLOCK_IO_PROTOCOL     *BlockIo;
+  EFI_DEVICE_PATH_PROTOCOL  *NextNode;
+  UINTN                     NumHandles;
+  UINTN                     LoopIndex;
+  EFI_HANDLE                *AllHandles;
+  EFI_HANDLE                Handle;
+
+  //
+  // Get all BlockIo handles in system
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiBlockIoProtocolGuid,
+                  NULL,
+                  &NumHandles,
+                  &AllHandles
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Couldn't locate BlockIo protocol: %r\n", Status));
+    return Status;
+  }
+
+  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
+    Status = gBS->OpenProtocol (
+                    AllHandles[LoopIndex],
+                    &gEfiDevicePathProtocolGuid,
+                    (VOID **)&DevicePath,
+                    gImageHandle,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Couldn't locate DevicePath protocol: %r\n", Status));
+      return Status;
+    }
+
+    if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE (BootDevicePath))) {
+      BootDevicePath = DevicePath;
+      break;
+    }
+  }
+
+  DevicePath = BootDevicePath;
+  Status     = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePath, &Handle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Couldn't locate device status: %r\n", Status));
+    return Status;
+  }
+
+  Status = gBS->OpenProtocol (
+                  Handle,
+                  &gEfiBlockIoProtocolGuid,
+                  (VOID **)&BlockIo,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to get BlockIo: %r\n", Status));
+    return Status;
+  }
+
+  for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) {
+    Status = gBS->OpenProtocol (
+                    AllHandles[LoopIndex],
+                    &gEfiDevicePathProtocolGuid,
+                    (VOID **)&DevicePath,
+                    gImageHandle,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Couldn't locate DevicePath protocol: %r\n", Status));
+      return Status;
+    }
+
+    if (!CompareMem (DevicePath, BootDevicePath, FLASH_DEVICE_PATH_SIZE (BootDevicePath))) {
+      NextNode = NextDevicePathNode (DevicePath);
+
+      while (!IsDevicePathEndType (NextNode)) {
+        if ((NextNode->Type == MEDIA_DEVICE_PATH) &&
+            (NextNode->SubType == MEDIA_HARDDRIVE_DP))
+        {
+          break;
+        }
+
+        NextNode = NextDevicePathNode (NextNode);
+      }
+
+      if (IsDevicePathEndType (NextNode)) {
+        continue;
+      }
+
+      break;
+    }
+  }
+
+  if (LoopIndex >= NumHandles) {
+    return EFI_LOAD_ERROR;
+  }
+
+  *PartitionDevicePath = DevicePath;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get capsule paritioin information.
+
+  @param[in]  VOID
+
+  @retval EFI_SUCCESS             Operation completed successfully.
+  @retval others                  Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsulePathInfo (
+  VOID
+  )
+{
+  mBootDevicePath = ConvertTextToDevicePath ((CHAR16 *)PcdGetPtr (PcdNVMeDevicePath));
+
+  if (mBootDevicePath == NULL) {
+    DEBUG ((DEBUG_ERROR, "mBootDevicePath is NULL\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Read Capsule file information from FAT partiton.
+
+  @param[in]  FileName              File name of Capsule binary
+  @param[out] Buffer                Return buffer pointer of Capsule binary
+  @param[out] BufferSize            Capsule binary size
+
+  @retval EFI_SUCCESS               Read Capsule information successfully
+  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate
+  @retval EFI_NOT_FOUND             Fail to read Capsule information
+  @retval Others                    Internal error when read Capsule information
+
+**/
+EFI_STATUS
+EFIAPI
+IterateAllCapsulesFromDisk (
+  IN CHAR16    *FileBaseName,
+  OUT VOID     **Buffer,
+  OUT UINTN    *BufferSize,
+  OUT BOOLEAN  *NoNextFile
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
+  EFI_FILE                         *Root;
+  EFI_FILE                         *DirHandle;
+  EFI_FILE                         *FileHandle;
+  EFI_FILE_INFO                    *FileInfo;
+  UINT8                            *FileBuffer;
+  EFI_HANDLE                       Handle;
+  EFI_BLOCK_IO_PROTOCOL            *BlockIo;
+  EFI_DEVICE_PATH_PROTOCOL         *BootPartitionPath;
+  BOOLEAN                          Found = FALSE;
+
+  FileBuffer = NULL;
+
+  DEBUG ((DEBUG_INFO, "ReadCapsuleInfo()...\n"));
+
+  Status = GetDevicePathByBoot (mBootDevicePath, &BootPartitionPath);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status));
+    return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, "IGpuDevicePath: %S\n", ConvertDevicePathToText (BootPartitionPath, FALSE, FALSE)));
+
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BootPartitionPath, &Handle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  //
+  // Get Capsule file
+  //
+  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 1Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  if (BlockIo->Media->RemovableMedia) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 2Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 3Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  Status = Fs->OpenVolume (Fs, &Root);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 4Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  Status = Root->Open (Root, &DirHandle, FileBaseName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Cannot open %s. Status = %r\n", FileBaseName, Status));
+    return Status;
+  }
+
+  //
+  // Get file count first
+  //
+  Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
+  while (!*NoNextFile && !Found) {
+    // . & ..
+    Status = FileHandleFindNextFile (DirHandle, FileInfo, NoNextFile);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    if (FileInfo->Attribute & EFI_FILE_DIRECTORY) {
+      continue;
+    }
+
+    Found = TRUE;
+  }
+
+  if (!Found) {
+    *NoNextFile = TRUE;
+    return EFI_NOT_FOUND;
+  }
+
+  DEBUG ((DEBUG_INFO, "Processing Capsule %s\n", FileInfo->FileName));
+  FileBuffer = AllocateZeroPool (FileInfo->FileSize);
+  if (FileBuffer == NULL) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  Status = DirHandle->Open (DirHandle, &FileHandle, FileInfo->FileName, EFI_FILE_MODE_READ, 0);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo Cannot open file %s: %r\n", FileInfo->FileName, Status));
+    FreePool (FileBuffer);
+    return Status;
+  }
+
+  Status = FileHandleRead (FileHandle, &FileInfo->FileSize, FileBuffer);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 7Locate DevicePath failed: %r\n", Status));
+    FileHandleClose (FileHandle);
+    FreePool (FileBuffer);
+    return Status;
+  }
+
+  if (!*NoNextFile) {
+    Status = FileHandleClose (DirHandle);
+  }
+
+  Status = FileHandleClose (FileHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 8Locate DevicePath failed: %r\n", Status));
+    FreePool (FileBuffer);
+    return Status;
+  }
+
+  *Buffer     = FileBuffer;
+  *BufferSize = FileInfo->FileSize;
+
+  DEBUG ((DEBUG_INFO, "Capsule size: 0x%x\n", *BufferSize));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Read Capsule file information from FAT partiton.
+
+  @param[in]  FileBaseName              File name of Capsule binary
+
+  @retval EFI_SUCCESS               Delete first capsule successfully
+  @retval EFI_NOT_FOUND             Fail to found Capsule information
+
+**/
+EFI_STATUS
+EFIAPI
+DeleteFirstCapsule (
+  CHAR16  *FileBaseName
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL         *BootPartitionPath;
+  EFI_HANDLE                       Handle;
+  EFI_STATUS                       Status;
+  EFI_BLOCK_IO_PROTOCOL            *BlockIo;
+  EFI_FILE_PROTOCOL                *Root;
+  EFI_FILE_HANDLE                  DirHandle;
+  BOOLEAN                          NoNextFile = FALSE;
+  EFI_FILE_INFO                    *FileInfo;
+  BOOLEAN                          Found = FALSE;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *Fs;
+  EFI_FILE_HANDLE                  FileHandle;
+
+  Status = GetDevicePathByBoot (mBootDevicePath, &BootPartitionPath);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "GetDevicePathByName failed: %r\n", Status));
+    return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, "IGpuDevicePath: %S\n", ConvertDevicePathToText (BootPartitionPath, FALSE, FALSE)));
+
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BootPartitionPath, &Handle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  //
+  // Get Capsule file
+  //
+  Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 1Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  if (BlockIo->Media->RemovableMedia) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 2Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 3Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  Status = Fs->OpenVolume (Fs, &Root);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ReadCapsuleInfo: 4Locate DevicePath failed: %r\n", Status));
+    return Status;
+  }
+
+  Status = Root->Open (Root, &DirHandle, FileBaseName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Cannot open %s. Status = %r\n", FileBaseName, Status));
+    return Status;
+  }
+
+  Status = FileHandleFindFirstFile (DirHandle, &FileInfo);
+  while (!NoNextFile && !Found) {
+    // . & ..
+    FileHandleFindNextFile (DirHandle, FileInfo, &NoNextFile);
+    if (FileInfo->Attribute & EFI_FILE_DIRECTORY) {
+      continue;
+    }
+
+    Found = TRUE;
+  }
+
+  if (!Found) {
+    return EFI_NOT_FOUND;
+  }
+
+  DEBUG ((DEBUG_INFO, "Deleting Capsule %s\n", FileInfo->FileName));
+  Status = DirHandle->Open (DirHandle, &FileHandle, FileInfo->FileName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0);
+  if (!EFI_ERROR (Status)) {
+    Status = FileHandle->Delete (FileHandle);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_INFO, "Cannot delete Capsule %s:%r\n", FileInfo->FileName, Status));
+    }
+
+    DirHandle->Close (DirHandle);
+    Root->Close (Root);
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Detect Capsule file from ESP partition and update capsule.
+
+  @retval EFI_SUCCESS               Opertion is successful.
+  @retval EFI_OUT_OF_RESOURCES      No enough buffer to allocate.
+  @retval EFI_ERROR                 Internal error when update Capsule.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsuleUpdateViaFileLib (
+  VOID
+  )
+{
+  EFI_STATUS          Status;
+  UINT8               *CapsuleBuffer;
+  UINTN               CapsuleSize;
+  EFI_CAPSULE_HEADER  *CapsuleHeader;
+  UINTN               CapsuleNum;
+  UINTN               CurrentCapsuleFileNo = 0;
+  BOOLEAN             NoNextFile           = FALSE;
+
+  CapsuleBuffer = NULL;
+  CapsuleSize   = 0;
+
+  DEBUG ((DEBUG_INFO, "CapsuleUpdateViaFileHook() Entry Point...\n"));
+
+  Status = CapsulePathInfo ();
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "CapsulePathInfo failed: %r\n", Status));
+    return Status;
+  }
+
+  while (!NoNextFile) {
+    Status = IterateAllCapsulesFromDisk (EFI_CAPSULE_FILE_DIRECTORY, (VOID **)&CapsuleBuffer, &CapsuleSize, &NoNextFile);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Failed to update capsule:%r\n", Status));
+      break;
+    }
+
+    CapsuleHeader = (EFI_CAPSULE_HEADER *)CapsuleBuffer;
+    CapsuleNum    = 1;
+    Status        = UpdateCapsule (&CapsuleHeader, CapsuleNum);
+    RecordCapsuleStatusVariable (CapsuleHeader, Status);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Failed to update capsule.\n"));
+      break;
+    }
+
+    Status = DeleteFirstCapsule (EFI_CAPSULE_FILE_DIRECTORY);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Cannot delete Capsule.\n"));
+      break;
+    }
+  }
+
+  if (CapsuleBuffer != NULL) {
+    FreePool (CapsuleBuffer);
+  }
+
+  if (!CurrentCapsuleFileNo && (Status == EFI_NOT_FOUND)) {
+    Status = EFI_SUCCESS;
+  }
+
+  DEBUG ((DEBUG_INFO, "Capsule update via file completed, Status=%r\n", Status));
+  // RecordFmpCapsuleStatus();
+  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+
+  // Unreachable.
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.inf b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.inf
new file mode 100644
index 0000000000..c3e910007a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/CapsuleHookLib/CapsuleHookLib.inf
@@ -0,0 +1,56 @@
+## @file
+# Capsule Hook Lib Module
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = CapsuleHookLib
+  FILE_GUID                      = 22BC4D9A-C78A-4038-8071-865765C4C019
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = CapsuleHookLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  CapsuleHookLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  BaseLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  BaseMemoryLib
+  DebugLib
+  UefiLib
+  FileHandleLib
+  DxeServicesLib
+  CapsuleLib
+
+[Protocols]
+  gEfiBlockIoProtocolGuid
+  gEfiSimpleFileSystemProtocolGuid
+
+[Pcd]
+  gAmdCommonPkgTokenSpaceGuid.PcdOtaCapsuleName
+  gAmdCommonPkgTokenSpaceGuid.PcdOtaCapsulePartitionName
+  gPlatformPkgTokenSpaceGuid.PcdNVMeDevicePath
+
+[Guids]
+  gEfiFmpCapsuleGuid
+  gEfiGlobalVariableGuid
+  gOtaCapsuleUpdateGuid
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.c b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.c
new file mode 100644
index 0000000000..94f4f8207a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.c
@@ -0,0 +1,794 @@
+/** @file
+  This file include all platform action which can be customized
+  by IBV/OEM.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+//
+// PCI Vendor ID and Device ID
+//
+#define VENDOR_ID   0x1002
+#define DEVICE_ID   0x163F
+#define DEVICE_ID2  0x1435
+
+#include "PlatformBootManager.h"
+#include "PlatformConsole.h"
+#include <Protocol/PlatformBootManagerOverride.h>
+#include <Guid/BootManagerMenu.h>
+#include <Library/HobLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/CapsuleHookLib.h>
+#include <Library/CapsuleLib.h>
+
+//
+// Predefined platform root bridge
+//
+PLATFORM_ROOT_BRIDGE_DEVICE_PATH  gPlatformRootBridge0 = {
+  gPciRootBridge,
+  gEndEntire
+};
+
+EFI_DEVICE_PATH_PROTOCOL  *gPlatformRootBridges[] = {
+  (EFI_DEVICE_PATH_PROTOCOL *)&gPlatformRootBridge0,
+  NULL
+};
+
+extern EFI_GUID                                            gEfiEventReadyToBootGuid;
+UNIVERSAL_PAYLOAD_PLATFORM_BOOT_MANAGER_OVERRIDE_PROTOCOL  *mUniversalPayloadPlatformBootManagerOverrideInstance = NULL;
+
+EFI_STATUS
+GetGopDevicePath (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *PciDevicePath,
+  OUT EFI_DEVICE_PATH_PROTOCOL  **GopDevicePath
+  );
+
+/**
+  Signal EndOfDxe event and install SMM Ready to lock protocol.
+
+**/
+VOID
+InstallReadyToLock (
+  VOID
+  )
+{
+  EFI_STATUS                Status;
+  EFI_HANDLE                Handle;
+  EFI_SMM_ACCESS2_PROTOCOL  *SmmAccess;
+
+  DEBUG ((DEBUG_INFO, "InstallReadyToLock  entering......\n"));
+  //
+  // Inform the SMM infrastructure that we're entering BDS and may run 3rd party code hereafter
+  // Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth
+  //
+  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
+  DEBUG ((DEBUG_INFO, "All EndOfDxe callbacks have returned successfully\n"));
+
+  //
+  // Install DxeSmmReadyToLock protocol in order to lock SMM
+  //
+  Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
+  if (!EFI_ERROR (Status)) {
+    Handle = NULL;
+    Status = gBS->InstallProtocolInterface (
+                    &Handle,
+                    &gEfiDxeSmmReadyToLockProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    NULL
+                    );
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  DEBUG ((DEBUG_INFO, "InstallReadyToLock  end\n"));
+  return;
+}
+
+/**
+  Return the index of the load option in the load option array.
+
+  The function consider two load options are equal when the
+  OptionType, Attributes, Description, FilePath and OptionalData are equal.
+
+  @param Key    Pointer to the load option to be found.
+  @param Array  Pointer to the array of load options to be found.
+  @param Count  Number of entries in the Array.
+
+  @retval -1          Key wasn't found in the Array.
+  @retval 0 ~ Count-1 The index of the Key in the Array.
+**/
+INTN
+PlatformFindLoadOption (
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION  *Key,
+  IN CONST EFI_BOOT_MANAGER_LOAD_OPTION  *Array,
+  IN UINTN                               Count
+  )
+{
+  UINTN  Index;
+
+  for (Index = 0; Index < Count; Index++) {
+    if ((Key->OptionType == Array[Index].OptionType) &&
+        (Key->Attributes == Array[Index].Attributes) &&
+        (StrCmp (Key->Description, Array[Index].Description) == 0) &&
+        (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
+        (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
+        (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0))
+    {
+      return (INTN)Index;
+    }
+  }
+
+  return -1;
+}
+
+/**
+  Register a boot option using a file GUID in the FV.
+
+  @param FileGuid     The file GUID name in FV.
+  @param Description  The boot option description.
+  @param Attributes   The attributes used for the boot option loading.
+**/
+VOID
+PlatformRegisterFvBootOption (
+  EFI_GUID  *FileGuid,
+  CHAR16    *Description,
+  UINT32    Attributes
+  )
+{
+  EFI_STATUS                         Status;
+  UINTN                              OptionIndex;
+  EFI_BOOT_MANAGER_LOAD_OPTION       NewOption;
+  EFI_BOOT_MANAGER_LOAD_OPTION       *BootOptions;
+  UINTN                              BootOptionCount;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;
+  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
+  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
+
+  Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);
+  ASSERT_EFI_ERROR (Status);
+
+  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+  DevicePath = AppendDevicePathNode (
+                 DevicePathFromHandle (LoadedImage->DeviceHandle),
+                 (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
+                 );
+
+  Status = EfiBootManagerInitializeLoadOption (
+             &NewOption,
+             LoadOptionNumberUnassigned,
+             LoadOptionTypeBoot,
+             Attributes,
+             Description,
+             DevicePath,
+             NULL,
+             0
+             );
+  if (!EFI_ERROR (Status)) {
+    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+
+    OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);
+
+    if (OptionIndex == -1) {
+      Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN)-1);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    EfiBootManagerFreeLoadOption (&NewOption);
+    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+  }
+}
+
+/**
+  Get device path of one IGPU and one DGPU.
+
+  @param IGpuDevicePath   Return the IGPU devide path, if no, return NULL.
+  @param DGpuDevicePath   Return the DGPU devide path, if no, return NULL.
+
+  @retval EFI_SUCCSS      Get all platform active video device path.
+  @retval EFI_STATUS      Return the status of gBS->LocateDevicePath (),
+                          gBS->ConnectController (),
+                          and gBS->LocateHandleBuffer ().
+**/
+EFI_STATUS
+GetVgaDevicePath (
+  IN OUT EFI_DEVICE_PATH_PROTOCOL  **IGpuDevicePath,
+  IN OUT EFI_DEVICE_PATH_PROTOCOL  **DGpuDevicePath
+  )
+{
+  EFI_STATUS                Status;
+  EFI_HANDLE                RootHandle;
+  UINTN                     HandleCount;
+  EFI_HANDLE                *HandleBuffer;
+  UINTN                     Index;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_PCI_IO_PROTOCOL       *PciIo;
+  PCI_TYPE00                Pci;
+
+  DEBUG ((DEBUG_INFO, "GetVgaDevicePath enter\n"));
+
+  HandleCount     = 0;
+  DevicePath      = NULL;
+  HandleBuffer    = NULL;
+  *IGpuDevicePath = NULL;
+  *DGpuDevicePath = NULL;
+
+  DEBUG ((DEBUG_INFO, "VENDOR_ID = 0x%x\n", VENDOR_ID));
+  DEBUG ((DEBUG_INFO, "DEVICE_ID = 0x%x\n", DEVICE_ID));
+
+  //
+  // Make all the PCI_IO protocols on PCI Seg 0 show up
+  //
+  EfiBootManagerConnectDevicePath (gPlatformRootBridges[0], NULL);
+
+  Status = gBS->LocateDevicePath (
+                  &gEfiDevicePathProtocolGuid,
+                  &gPlatformRootBridges[0],
+                  &RootHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->ConnectController (
+                  RootHandle,
+                  NULL,
+                  NULL,
+                  FALSE
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Start to check all the pci io to find all possible VGA device
+  //
+  HandleCount  = 0;
+  HandleBuffer = NULL;
+  Status       = gBS->LocateHandleBuffer (
+                        ByProtocol,
+                        &gEfiPciIoProtocolGuid,
+                        NULL,
+                        &HandleCount,
+                        &HandleBuffer
+                        );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->HandleProtocol (
+                    HandleBuffer[Index],
+                    &gEfiPciIoProtocolGuid,
+                    (VOID **)&PciIo
+                    );
+    if (!EFI_ERROR (Status)) {
+      //
+      // Check for all VGA device
+      //
+      Status = PciIo->Pci.Read (
+                            PciIo,
+                            EfiPciIoWidthUint32,
+                            0,
+                            sizeof (Pci) / sizeof (UINT32),
+                            &Pci
+                            );
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      //
+      // Here we decide which VGA device to enable in PCI bus
+      //
+      // The first plugin PCI VGA card device will be present as PCI VGA
+      // The onchip AGP or AGP card will be present as AGP VGA
+      //
+      if (!IS_PCI_DISPLAY (&Pci)) {
+        // if (!IS_PCI_VGA (&Pci)) {
+        continue;
+      }
+
+      //
+      // Set the device as the possible console out device,
+      //
+      // Below code will make every VGA device to be one
+      // of the possibe console out device
+      //
+      gBS->HandleProtocol (
+             HandleBuffer[Index],
+             &gEfiDevicePathProtocolGuid,
+             (VOID **)&DevicePath
+             );
+      DEBUG ((DEBUG_INFO, "DevicePath: %S\n", ConvertDevicePathToText (DevicePath, FALSE, FALSE)));
+
+      if ((Pci.Hdr.VendorId == VENDOR_ID) && ((Pci.Hdr.DeviceId == DEVICE_ID) || (Pci.Hdr.DeviceId == DEVICE_ID2))) {
+        // IGPU
+        *IGpuDevicePath = DevicePath;
+      } else {
+        // DGPU
+        *DGpuDevicePath = DevicePath;
+      }
+
+      if ((*IGpuDevicePath != NULL) && (*DGpuDevicePath != NULL)) {
+        DEBUG ((DEBUG_INFO, "IGpuDevicePath and DGpuDevicePath are not NULL\n"));
+        break;
+      }
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "IGpuDevicePath: %S\n", ConvertDevicePathToText (*IGpuDevicePath, FALSE, FALSE)));
+  DEBUG ((DEBUG_INFO, "DGpuDevicePath: %S\n", ConvertDevicePathToText (*DGpuDevicePath, FALSE, FALSE)));
+  FreePool (HandleBuffer);
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Find the platform active vga, and base on the policy to enable the vga as
+  the console out device. The policy is active dGPU, if no dGPU active iGPU.
+
+  None.
+
+  @param EFI_UNSUPPORTED         There is no active vga device
+
+  @retval EFI_STATUS             Return the status of BdsLibGetVariableAndSize ()
+
+**/
+EFI_STATUS
+PlatformBdsForceActiveVga (
+  VOID
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathFirst;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathSecond;
+  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *IGpuDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *DGpuDevicePath;
+
+  DEBUG ((DEBUG_INFO, "PlatformBdsForceActiveVga enter\n"));
+
+  Status           = EFI_SUCCESS;
+  DevicePathFirst  = NULL;
+  DevicePathSecond = NULL;
+  GopDevicePath    = NULL;
+  IGpuDevicePath   = NULL;
+  DGpuDevicePath   = NULL;
+
+  //
+  // Get device path of one IGPU and one DGPU
+  //
+  Status = GetVgaDevicePath (&IGpuDevicePath, &DGpuDevicePath);
+  ASSERT_EFI_ERROR (Status);
+
+  if ((IGpuDevicePath == NULL) && (DGpuDevicePath == NULL)) {
+    DEBUG ((DEBUG_INFO, "No valid IGPU and DGPU\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  if ((IGpuDevicePath != NULL) && (DGpuDevicePath == NULL)) {
+    DEBUG ((DEBUG_INFO, "Only IGPU is valid\n"));
+    // DEBUG ((DEBUG_INFO,"Only IGPU is valid, Update IGPU ...\n"));
+    DevicePathFirst  = IGpuDevicePath;
+    DevicePathSecond = DGpuDevicePath;
+    goto UpdateConOut;
+  } else if ((IGpuDevicePath == NULL) && (DGpuDevicePath != NULL)) {
+    DEBUG ((DEBUG_INFO, "Only DGPU is valid\n"));
+    // DEBUG ((DEBUG_INFO,"Only DGPU is valid, Update DGPU ...\n"));
+    DevicePathFirst  = DGpuDevicePath;
+    DevicePathSecond = IGpuDevicePath;
+    goto UpdateConOut;
+  } else if ((IGpuDevicePath != NULL) && (DGpuDevicePath != NULL)) {
+    DEBUG ((DEBUG_INFO, "DGPU and IGPU are valid, active DGPU\n"));
+    // DEBUG ((DEBUG_INFO,"Only DGPU is valid, Update DGPU ...\n"));
+    DevicePathFirst  = DGpuDevicePath;
+    DevicePathSecond = IGpuDevicePath;
+    goto UpdateConOut;
+  }
+
+UpdateConOut:
+  DEBUG ((DEBUG_INFO, "Before GetGopDevicePath: ConOutDevicePath is %S\n", ConvertDevicePathToText (DevicePathFirst, FALSE, FALSE)));
+  GetGopDevicePath (DevicePathFirst, &GopDevicePath);
+  DevicePathFirst = GopDevicePath;
+  DEBUG ((DEBUG_INFO, "After GetGopDevicePath: ConOutDevicePath is %S\n", ConvertDevicePathToText (DevicePathFirst, FALSE, FALSE)));
+  DEBUG ((DEBUG_INFO, "Exclusive device path is %S\n", ConvertDevicePathToText (DevicePathSecond, FALSE, FALSE)));
+
+  Status = EfiBootManagerUpdateConsoleVariable (
+             ConOut,
+             DevicePathFirst,
+             DevicePathSecond
+             );
+  // TODO: Specify iGPU/dGPU.
+  EfiBootManagerConnectVideoController (NULL);
+  return Status;
+}
+
+/**
+  Do the platform specific action before the console is connected.
+
+  Such as:
+    Update console variable;
+    Register new Driver#### or Boot####;
+    Signal ReadyToLock event.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+  VOID
+  )
+{
+  EFI_INPUT_KEY                 Enter;
+  EFI_INPUT_KEY                 CustomKey;
+  EFI_INPUT_KEY                 Down;
+  EFI_BOOT_MANAGER_LOAD_OPTION  BootOption;
+  EFI_STATUS                    Status;
+  UINT64                        OsIndication;
+  UINTN                         DataSize;
+  UINT32                        Attributes;
+  BOOLEAN                       CapsuleUpdateonDisk;
+
+  Status = gBS->LocateProtocol (&gUniversalPayloadPlatformBootManagerOverrideProtocolGuid, NULL, (VOID **)&mUniversalPayloadPlatformBootManagerOverrideInstance);
+  if (EFI_ERROR (Status)) {
+    mUniversalPayloadPlatformBootManagerOverrideInstance = NULL;
+  }
+
+  Status = gRT->GetVariable (
+                  L"OsIndications",
+                  &gEfiGlobalVariableGuid,
+                  &Attributes,
+                  &DataSize,
+                  &OsIndication
+                  );
+  if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {
+    mUniversalPayloadPlatformBootManagerOverrideInstance->BeforeConsole ();
+    return;
+  }
+
+  //
+  // Register ENTER as CONTINUE key
+  //
+  Enter.ScanCode    = SCAN_NULL;
+  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+  EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+
+  if (FixedPcdGetBool (PcdBootManagerEscape)) {
+    //
+    // Map Esc to Boot Manager Menu
+    //
+    CustomKey.ScanCode    = SCAN_ESC;
+    CustomKey.UnicodeChar = CHAR_NULL;
+  } else {
+    //
+    // Map Esc to Boot Manager Menu
+    //
+    CustomKey.ScanCode    = SCAN_F2;
+    CustomKey.UnicodeChar = CHAR_NULL;
+  }
+
+  EfiBootManagerGetBootManagerMenu (&BootOption);
+  EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumber, 0, &CustomKey, NULL);
+
+  //
+  // Also add Down key to Boot Manager Menu since some serial terminals don't support F2 key.
+  //
+  Down.ScanCode    = SCAN_DOWN;
+  Down.UnicodeChar = CHAR_NULL;
+  EfiBootManagerGetBootManagerMenu (&BootOption);
+  EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)BootOption.OptionNumber, 0, &Down, NULL);
+  CapsuleUpdateonDisk = (BOOLEAN)((OsIndication & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) != 0);
+  // Process Capsule in Memory first, before EndOfDxe.
+  if ((GetBootModeHob () == BOOT_ON_FLASH_UPDATE) || CapsuleUpdateonDisk) {
+    PlatformBdsForceActiveVga (); // Force enable VGA on Capsule Update.
+    ASSERT_EFI_ERROR (BootLogoEnableLogo ());
+    Print (
+      L"\n"
+      L"    Updating system BIOS.....\n"
+      L"\n"
+      );
+    if (CapsuleUpdateonDisk) {
+      EfiBootManagerConnectAll (); // Get BlockIo
+      CapsuleUpdateViaFileLib ();
+    } else {
+      ProcessCapsules ();
+    }
+  }
+
+  //
+  // Install ready to lock.
+  // This needs to be done before option rom dispatched.
+  //
+  InstallReadyToLock ();
+
+  //
+  // Dispatch deferred images after EndOfDxe event and ReadyToLock installation.
+  //
+  EfiBootManagerDispatchDeferredImages ();
+
+  PlatformConsoleInit ();
+}
+
+/**
+  Do the platform specific action after the console is connected.
+
+  Such as:
+    Dynamically switch output mode;
+    Signal console ready platform customized event;
+    Run diagnostics like memory testing;
+    Connect certain devices;
+    Dispatch additional option roms.
+**/
+VOID
+EFIAPI
+PlatformBootManagerAfterConsole (
+  VOID
+  )
+{
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Black;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL  White;
+  EDKII_PLATFORM_LOGO_PROTOCOL   *PlatformLogo;
+  EFI_STATUS                     Status;
+  UINT64                         OsIndication;
+  UINTN                          DataSize;
+  UINT32                         Attributes;
+
+  if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {
+    mUniversalPayloadPlatformBootManagerOverrideInstance->AfterConsole ();
+    return;
+  }
+
+  Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;
+  White.Blue = White.Green = White.Red = White.Reserved = 0xFF;
+
+  Status = gBS->LocateProtocol (&gEdkiiPlatformLogoProtocolGuid, NULL, (VOID **)&PlatformLogo);
+
+  if (!EFI_ERROR (Status)) {
+    gST->ConOut->ClearScreen (gST->ConOut);
+    BootLogoEnableLogo ();
+  }
+
+  EfiBootManagerConnectAll ();
+  EfiBootManagerRefreshAllBootOption ();
+
+  // Process Capsule in Memory again, after EndOfDxe.
+  if (GetBootModeHob () == BOOT_ON_FLASH_UPDATE) {
+    ProcessCapsules ();
+  }
+
+  OsIndication = 0;
+  Attributes   = 0;
+  DataSize     = sizeof (UINT64);
+  Status       = gRT->GetVariable (
+                        EFI_OS_INDICATIONS_VARIABLE_NAME,
+                        &gEfiGlobalVariableGuid,
+                        &Attributes,
+                        &DataSize,
+                        &OsIndication
+                        );
+  if (EFI_ERROR (Status)) {
+    OsIndication = 0;
+  }
+
+  //
+  // Register UEFI Shell
+  //
+  PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE);
+
+  {
+    if (FixedPcdGetBool (PcdBootManagerEscape)) {
+      Print (
+        L"\n"
+        L"    Esc or Down      to enter Boot Manager Menu.\n"
+        L"    ENTER            to boot directly.\n"
+        L"\n"
+        );
+    } else {
+      Print (
+        L"\n"
+        L"    F2 or Down      to enter Boot Manager Menu.\n"
+        L"    ENTER           to boot directly.\n"
+        L"\n"
+        );
+    }
+  }
+}
+
+/**
+  This function is called each second during the boot manager waits the timeout.
+
+  @param TimeoutRemain  The remaining timeout.
+**/
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+  UINT16  TimeoutRemain
+  )
+{
+  if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {
+    mUniversalPayloadPlatformBootManagerOverrideInstance->WaitCallback (TimeoutRemain);
+  }
+
+  return;
+}
+
+/**
+  The function is called when no boot option could be launched,
+  including platform recovery options and options pointing to applications
+  built into firmware volumes.
+
+  If this function returns, BDS attempts to enter an infinite loop.
+**/
+VOID
+EFIAPI
+PlatformBootManagerUnableToBoot (
+  VOID
+  )
+{
+  if (mUniversalPayloadPlatformBootManagerOverrideInstance != NULL) {
+    mUniversalPayloadPlatformBootManagerOverrideInstance->UnableToBoot ();
+  }
+
+  return;
+}
+
+typedef struct {
+  UINTN                   Signature;
+  LIST_ENTRY              Link;
+  EFI_PHYSICAL_ADDRESS    StartAddress;
+  UINT64                  Length;
+  UINT64                  Capabilities;
+} NONTESTED_MEMORY_RANGE;
+
+//
+// This structure records every nontested memory range parsed through GCD
+// service.
+//
+#define EFI_NONTESTED_MEMORY_RANGE_SIGNATURE  SIGNATURE_32 ('N', 'T', 'M', 'E')
+
+//
+// attributes for reserved memory before it is promoted to system memory
+//
+#define EFI_MEMORY_PRESENT      0x0100000000000000ULL
+#define EFI_MEMORY_INITIALIZED  0x0200000000000000ULL
+#define EFI_MEMORY_TESTED       0x0400000000000000ULL
+
+/**
+  Callback function for event group EFI_EVENT_GROUP_READY_TO_BOOT.
+  This is used to expose the 4G above memory into system memory table.
+
+  @param[in]  Event      The Event that is being processed.
+  @param[in]  Context    The Event Context.
+
+**/
+VOID
+EFIAPI
+ExposeOver4GMemoryEventCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  NONTESTED_MEMORY_RANGE           *Range;
+  BOOLEAN                          NoFound;
+  UINTN                            NumberOfDescriptors;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMap;
+  UINTN                            Index;
+  LIST_ENTRY                       *TmpLink;
+  LIST_ENTRY                       NonTestedMemRanList;
+
+  DEBUG ((DEBUG_INFO, "ExposeOver4GMemoryEventCallback\n"));
+
+  TmpLink = NULL;
+  NoFound = TRUE;
+
+  InitializeListHead (&NonTestedMemRanList);
+
+  gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
+  for (Index = 0; Index < NumberOfDescriptors; Index++) {
+    if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved) &&
+        ((MemorySpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
+         (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED))
+        )
+    {
+      NoFound = FALSE;
+
+      gBS->AllocatePool (EfiBootServicesData, sizeof (NONTESTED_MEMORY_RANGE), (VOID **)&Range);
+
+      Range->Signature    = EFI_NONTESTED_MEMORY_RANGE_SIGNATURE;
+      Range->StartAddress = MemorySpaceMap[Index].BaseAddress;
+      Range->Length       = MemorySpaceMap[Index].Length;
+      Range->Capabilities = MemorySpaceMap[Index].Capabilities;
+
+      InsertTailList (&NonTestedMemRanList, &Range->Link);
+    }
+  }
+
+  if (!NoFound) {
+    TmpLink = NonTestedMemRanList.ForwardLink;
+
+    while (TmpLink != &NonTestedMemRanList) {
+      Range = CR (TmpLink, NONTESTED_MEMORY_RANGE, Link, EFI_NONTESTED_MEMORY_RANGE_SIGNATURE);
+      gDS->RemoveMemorySpace (Range->StartAddress, Range->Length);
+      gDS->AddMemorySpace (
+             EfiGcdMemoryTypeSystemMemory,
+             Range->StartAddress,
+             Range->Length,
+             Range->Capabilities &~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)
+             );
+
+      TmpLink = TmpLink->ForwardLink;
+    }
+  }
+
+  //
+  // Make sure the hook ONLY called once.
+  //
+  if (Event != NULL) {
+    gBS->CloseEvent (Event);
+  }
+}
+
+/**
+  Get/update PcdBootManagerMenuFile from GUID HOB which will be assigned in bootloader.
+
+  @param  ImageHandle   The firmware allocated handle for the EFI image.
+  @param  SystemTable   A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformBootManagerLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                           Status;
+  UINTN                                Size;
+  VOID                                 *GuidHob;
+  UNIVERSAL_PAYLOAD_GENERIC_HEADER     *GenericHeader;
+  UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU  *BootManagerMenuFile;
+
+  EFI_EVENT  ExposeOver4GMemoryEvent;
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  ExposeOver4GMemoryEventCallback,
+                  NULL,
+                  &gEfiEventReadyToBootGuid,
+                  &ExposeOver4GMemoryEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  GuidHob = GetFirstGuidHob (&gEdkiiBootManagerMenuFileGuid);
+
+  if (GuidHob == NULL) {
+    //
+    // If the HOB is not create, the default value of PcdBootManagerMenuFile will be used.
+    //
+    return EFI_SUCCESS;
+  }
+
+  GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob);
+  if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) > GET_GUID_HOB_DATA_SIZE (GuidHob)) || (GenericHeader->Length > GET_GUID_HOB_DATA_SIZE (GuidHob))) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (GenericHeader->Revision == UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU_REVISION) {
+    BootManagerMenuFile = (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU *)GET_GUID_HOB_DATA (GuidHob);
+    if (BootManagerMenuFile->Header.Length < UNIVERSAL_PAYLOAD_SIZEOF_THROUGH_FIELD (UNIVERSAL_PAYLOAD_BOOT_MANAGER_MENU, FileName)) {
+      return EFI_NOT_FOUND;
+    }
+
+    Size   = sizeof (BootManagerMenuFile->FileName);
+    Status = PcdSetPtrS (PcdBootManagerMenuFile, &Size, &BootManagerMenuFile->FileName);
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.h b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.h
new file mode 100644
index 0000000000..15891f9471
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManager.h
@@ -0,0 +1,150 @@
+/** @file
+   Head file for BDS Platform specific code
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef PLATFORM_BOOT_MANAGER_H_
+#define PLATFORM_BOOT_MANAGER_H_
+
+#include <PiDxe.h>
+#include <Protocol/LoadedImage.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/BootLogoLib.h>
+#include <Protocol/SmmAccess2.h>
+#include <Guid/GlobalVariable.h>
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
+  UINTN                       ConnectType;
+} PLATFORM_CONSOLE_CONNECT_ENTRY;
+
+extern PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];
+
+#define gEndEntire \
+  { \
+    END_DEVICE_PATH_TYPE,\
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\
+    { END_DEVICE_PATH_LENGTH, 0 },\
+  }
+
+#define CONSOLE_OUT  BIT0
+#define CONSOLE_IN   BIT1
+#define STD_ERROR    BIT2
+
+#define CLASS_HID          3
+#define SUBCLASS_BOOT      1
+#define PROTOCOL_KEYBOARD  1
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+  { \
+    { \
+      ACPI_DEVICE_PATH, \
+      ACPI_DP, \
+      { \
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+      }, \
+    }, \
+    EISA_PNP_ID((PnpId)), \
+    0 \
+  }
+
+#define gPciRootBridge \
+  PNPID_DEVICE_PATH_NODE(0x0A03)
+
+typedef struct {
+  USB_CLASS_DEVICE_PATH       UsbClass;
+  EFI_DEVICE_PATH_PROTOCOL    End;
+} USB_CLASS_FORMAT_DEVICE_PATH;
+
+typedef struct {
+  VENDOR_DEVICE_PATH    VendorDevicePath;
+  UINT32                Instance;
+} WIN_NT_VENDOR_DEVICE_PATH_NODE;
+
+//
+// Below is the platform console device path
+//
+typedef struct {
+  VENDOR_DEVICE_PATH                NtBus;
+  WIN_NT_VENDOR_DEVICE_PATH_NODE    SerialDevice;
+  UART_DEVICE_PATH                  Uart;
+  VENDOR_DEVICE_PATH                TerminalType;
+  EFI_DEVICE_PATH_PROTOCOL          End;
+} NT_ISA_SERIAL_DEVICE_PATH;
+
+typedef struct {
+  VENDOR_DEVICE_PATH                NtBus;
+  WIN_NT_VENDOR_DEVICE_PATH_NODE    NtGopDevice;
+  EFI_DEVICE_PATH_PROTOCOL          End;
+} NT_PLATFORM_GOP_DEVICE_PATH;
+
+extern USB_CLASS_FORMAT_DEVICE_PATH  gUsbClassKeyboardDevicePath;
+
+/**
+  Use SystemTable Conout to stop video based Simple Text Out consoles from going
+  to the video device. Put up LogoFile on every video device that is a console.
+
+  @param[in]  LogoFile   File name of logo to display on the center of the screen.
+
+  @retval EFI_SUCCESS     ConsoleControl has been flipped to graphics and logo displayed.
+  @retval EFI_UNSUPPORTED Logo not found
+
+**/
+EFI_STATUS
+PlatformBootManagerEnableQuietBoot (
+  IN  EFI_GUID  *LogoFile
+  );
+
+/**
+  Use SystemTable Conout to turn on video based Simple Text Out consoles. The
+  Simple Text Out screens will now be synced up with all non video output devices
+
+  @retval EFI_SUCCESS     UGA devices are back in text mode and synced up.
+
+**/
+EFI_STATUS
+PlatformBootManagerDisableQuietBoot (
+  VOID
+  );
+
+/**
+  Show progress bar with title above it. It only works in Graphics mode.
+
+  @param TitleForeground Foreground color for Title.
+  @param TitleBackground Background color for Title.
+  @param Title           Title above progress bar.
+  @param ProgressColor   Progress bar color.
+  @param Progress        Progress (0-100)
+  @param PreviousValue   The previous value of the progress.
+
+  @retval  EFI_STATUS       Success update the progress bar
+
+**/
+EFI_STATUS
+PlatformBootManagerShowProgress (
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL  TitleForeground,
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL  TitleBackground,
+  IN CHAR16                         *Title,
+  IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL  ProgressColor,
+  IN UINTN                          Progress,
+  IN UINTN                          PreviousValue
+  );
+
+#endif // _PLATFORM_BOOT_MANAGER_H
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManagerLib.inf
new file mode 100644
index 0000000000..fc9251d3fd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -0,0 +1,89 @@
+## @file
+#  Include all platform action which can be customized by IBV/OEM.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2012 - 2021, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformBootManagerLib
+  FILE_GUID                      = 9455F0BD-2037-488A-8899-56CB72A44A03
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformBootManagerLib|DXE_DRIVER
+  CONSTRUCTOR                    = PlatformBootManagerLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  PlatformData.c
+  PlatformConsole.c
+  PlatformConsole.h
+  PlatformBootManager.c
+  PlatformBootManager.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiPayloadPkg/UefiPayloadPkg.dec
+  AgesaPublic/AgesaPublic.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiLib
+  UefiBootManagerLib
+  BootLogoLib
+  PcdLib
+  DxeServicesLib
+  DxeServicesTableLib
+  MemoryAllocationLib
+  DevicePathLib
+  HiiLib
+  PrintLib
+  PlatformHookLib
+  HobLib
+  DebugLib
+  CapsuleLib
+  CapsuleHookLib
+
+[Guids]
+  gEfiEndOfDxeEventGroupGuid
+  gEdkiiBootManagerMenuFileGuid
+  gEfiEventReadyToBootGuid
+
+[Protocols]
+  gEfiGenericMemTestProtocolGuid  ## CONSUMES
+  gEfiGraphicsOutputProtocolGuid  ## CONSUMES
+  gEfiUgaDrawProtocolGuid         ## CONSUMES
+  gEfiBootLogoProtocolGuid        ## CONSUMES
+  gEfiDxeSmmReadyToLockProtocolGuid
+  gEfiSmmAccess2ProtocolGuid
+  gUniversalPayloadPlatformBootManagerOverrideProtocolGuid
+  gEfiSerialIoProtocolGuid
+  gEfiPciRootBridgeIoProtocolGuid
+  gAmdCpmAllPciIoProtocolsInstalledProtocolGuid
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+  gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand
+  gUefiPayloadPkgTokenSpaceGuid.PcdShellFile
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity
+  gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits
+  gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile
+  gUefiPayloadPkgTokenSpaceGuid.PcdBootManagerEscape
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.c b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.c
new file mode 100644
index 0000000000..4849770ff6
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.c
@@ -0,0 +1,495 @@
+/** @file
+This file include all platform action which can be customized by IBV/OEM.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PlatformBootManager.h"
+#include "PlatformConsole.h"
+#include <Guid/SerialPortLibVendor.h>
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+  { \
+    { \
+      HARDWARE_DEVICE_PATH, \
+      HW_PCI_DP, \
+      { \
+        (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    (Func), \
+    (Dev) \
+  }
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+  { \
+    { \
+      ACPI_DEVICE_PATH, \
+      ACPI_DP, \
+      { \
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+      }, \
+    }, \
+    EISA_PNP_ID((PnpId)), \
+    0 \
+  }
+
+#define gPnp16550ComPort \
+  PNPID_DEVICE_PATH_NODE(0x0501)
+
+#define gPnpPs2Keyboard \
+  PNPID_DEVICE_PATH_NODE(0x0303)
+
+#define gPcAnsiTerminal \
+  { \
+    { \
+      MESSAGING_DEVICE_PATH, \
+      MSG_VENDOR_DP, \
+      { \
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    DEVICE_PATH_MESSAGING_PC_ANSI \
+  }
+
+ACPI_HID_DEVICE_PATH  gPnpPs2KeyboardDeviceNode  = gPnpPs2Keyboard;
+ACPI_HID_DEVICE_PATH  gPnp16550ComPortDeviceNode = gPnp16550ComPort;
+VENDOR_DEVICE_PATH    gTerminalTypeDeviceNode    = gPcAnsiTerminal;
+
+BOOLEAN  mDetectDisplayOnly;
+
+/**
+  Add IsaKeyboard to ConIn.
+
+  @param[in] DeviceHandle  Handle of the LPC Bridge device.
+
+  @retval EFI_SUCCESS  IsaKeyboard on the LPC bridge have been added to ConIn.
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+                       from DeviceHandle.
+**/
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+  IN EFI_HANDLE  DeviceHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+
+  DevicePath = NULL;
+  Status     = gBS->HandleProtocol (
+                      DeviceHandle,
+                      &gEfiDevicePathProtocolGuid,
+                      (VOID *)&DevicePath
+                      );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Register Keyboard
+  //
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+  return EFI_SUCCESS;
+}
+
+/**
+  Return the GOP device path in the platform.
+
+  @param[in]   PciDevicePath - Device path for the PCI graphics device.
+  @param[out]  GopDevicePath - Return the device path with GOP installed.
+
+  @retval EFI_SUCCESS  - PCI VGA is added to ConOut.
+  @retval EFI_INVALID_PARAMETER   - The device path parameter is invalid.
+  @retval EFI_STATUS   - No GOP device found.
+**/
+EFI_STATUS
+GetGopDevicePath (
+  IN  EFI_DEVICE_PATH_PROTOCOL  *PciDevicePath,
+  OUT EFI_DEVICE_PATH_PROTOCOL  **GopDevicePath
+  )
+{
+  UINTN                     Index;
+  EFI_STATUS                Status;
+  EFI_HANDLE                PciDeviceHandle;
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempPciDevicePath;
+  UINTN                     GopHandleCount;
+  EFI_HANDLE                *GopHandleBuffer;
+
+  if ((PciDevicePath == NULL) || (GopDevicePath == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Initialize the GopDevicePath to be PciDevicePath
+  //
+  *GopDevicePath    = PciDevicePath;
+  TempPciDevicePath = PciDevicePath;
+
+  Status = gBS->LocateDevicePath (
+                  &gEfiDevicePathProtocolGuid,
+                  &TempPciDevicePath,
+                  &PciDeviceHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiGraphicsOutputProtocolGuid,
+                  NULL,
+                  &GopHandleCount,
+                  &GopHandleBuffer
+                  );
+  if (!EFI_ERROR (Status)) {
+    //
+    // Add all the child handles as possible Console Device
+    //
+    for (Index = 0; Index < GopHandleCount; Index++) {
+      Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *)&TempDevicePath);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+
+      if (CompareMem (
+            PciDevicePath,
+            TempDevicePath,
+            GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
+            ) == 0)
+      {
+        //
+        // In current implementation, we only enable one of the child handles
+        // as console device, i.e. sotre one of the child handle's device
+        // path to variable "ConOut"
+        // In future, we could select all child handles to be console device
+        //
+        *GopDevicePath = TempDevicePath;
+
+        //
+        // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
+        // Add the integrity GOP device path.
+        //
+        EfiBootManagerUpdateConsoleVariable (ConOut, NULL, PciDevicePath);
+        EfiBootManagerUpdateConsoleVariable (ConOut, TempDevicePath, NULL);
+      }
+    }
+
+    gBS->FreePool (GopHandleBuffer);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Add PCI VGA to ConOut, ConIn, ErrOut.
+
+  @param[in]  DeviceHandle - Handle of PciIo protocol.
+
+  @retval EFI_SUCCESS  - PCI VGA is added to ConOut.
+  @retval EFI_STATUS   - No PCI VGA device is added.
+
+**/
+EFI_STATUS
+PreparePciVgaDevicePath (
+  IN EFI_HANDLE  DeviceHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
+
+  DevicePath = NULL;
+  Status     = gBS->HandleProtocol (
+                      DeviceHandle,
+                      &gEfiDevicePathProtocolGuid,
+                      (VOID *)&DevicePath
+                      );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  GetGopDevicePath (DevicePath, &GopDevicePath);
+  DevicePath = GopDevicePath;
+
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  For every PCI instance execute a callback function.
+
+  @param[in]  Id                 - The protocol GUID for callback
+  @param[in]  CallBackFunction   - The callback function
+
+  @retval EFI_STATUS - Callback function failed.
+
+**/
+EFI_STATUS
+EFIAPI
+VisitAllInstancesOfProtocol (
+  IN EFI_GUID                           *Id,
+  IN SIMPLE_PROTOCOL_INSTANCE_CALLBACK  CallBackFunction
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       HandleCount;
+  EFI_HANDLE  *HandleBuffer;
+  UINTN       Index;
+  VOID        *Instance;
+
+  //
+  // Start to check all the PciIo to find all possible device
+  //
+  HandleCount  = 0;
+  HandleBuffer = NULL;
+  Status       = gBS->LocateHandleBuffer (
+                        ByProtocol,
+                        Id,
+                        NULL,
+                        &HandleCount,
+                        &HandleBuffer
+                        );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    Status = (*CallBackFunction)(
+  HandleBuffer[Index],
+  Instance
+  );
+  }
+
+  gBS->FreePool (HandleBuffer);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Do platform specific PCI Device check and add them to
+  ConOut, ConIn, ErrOut.
+
+  @param[in]  Handle    - Handle of PCI device instance
+  @param[in]  Instance  - The instance of PCI device
+
+  @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
+  @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+EFIAPI
+DetectAndPreparePlatformPciDevicePath (
+  IN EFI_HANDLE  Handle,
+  IN VOID        *Instance
+  )
+{
+  EFI_STATUS           Status;
+  EFI_PCI_IO_PROTOCOL  *PciIo;
+  PCI_TYPE00           Pci;
+
+  EFI_HANDLE  CPMHandle;
+
+  PciIo = (EFI_PCI_IO_PROTOCOL *)Instance;
+
+  //
+  // Check for all PCI device
+  //
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint32,
+                        0,
+                        sizeof (Pci) / sizeof (UINT32),
+                        &Pci
+                        );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationEnable,
+                    EFI_PCI_DEVICE_ENABLE,
+                    NULL
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  if (!mDetectDisplayOnly) {
+    //
+    // Here we decide whether it is LPC Bridge
+    //
+    if ((IS_PCI_LPC (&Pci)) ||
+        ((IS_PCI_ISA_PDECODE (&Pci)) &&
+         (Pci.Hdr.VendorId == 0x8086)
+        )
+        )
+    {
+      //
+      // Add IsaKeyboard to ConIn,
+      // add IsaSerial to ConOut, ConIn, ErrOut
+      //
+      DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
+      PrepareLpcBridgeDevicePath (Handle);
+      return EFI_SUCCESS;
+    }
+  }
+
+  //
+  // Enable all display devices
+  //
+  if (IS_PCI_DISPLAY (&Pci)) {
+    //
+    // Add them to ConOut.
+    //
+    DEBUG ((DEBUG_INFO, "Found PCI Display device\n"));
+    EfiBootManagerConnectVideoController (Handle);
+    //
+    // At this point, all the PCI_IO protocols are installed completely.
+    // Install gAmdCpmAllPciIoProtocolsInstalledProtocolGuid protocol for AmdCpmDisplayFeature DXE driver.
+    //
+    CPMHandle = NULL;
+    Status    = gBS->InstallProtocolInterface (
+                       &CPMHandle,
+                       &gAmdCpmAllPciIoProtocolsInstalledProtocolGuid,
+                       EFI_NATIVE_INTERFACE,
+                       NULL
+                       );
+    ASSERT_EFI_ERROR (Status);
+    DEBUG ((DEBUG_INFO, "InstallProtocolInterface gAmdCpmAllPciIoProtocolsInstalledProtocolGuid %r\n", Status));
+    return EFI_SUCCESS;
+  }
+
+  return Status;
+}
+
+/**
+  For every Serial Io instance, add it to ConOut, ConIn, ErrOut.
+
+  @param[in]  Handle     - The Serial Io device handle
+  @param[in]  Instance   - The instance of the SerialIo protocol
+
+  @retval EFI_STATUS - Callback function failed.
+
+**/
+EFI_STATUS
+EFIAPI
+AddDevicePathForOneSerialIoInstance (
+  IN EFI_HANDLE  Handle,
+  IN VOID        *Instance
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+
+  DevicePath = NULL;
+  Status     = gBS->HandleProtocol (
+                      Handle,
+                      &gEfiDevicePathProtocolGuid,
+                      (VOID *)&DevicePath
+                      );
+  DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+  return Status;
+}
+
+/**
+  Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+
+  @param[in]  DetectDisplayOnly - Only detect display device if it's TRUE.
+
+  @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
+  @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+DetectAndPreparePlatformPciDevicePaths (
+  BOOLEAN  DetectDisplayOnly
+  )
+{
+  EFI_STATUS  Status;
+
+  mDetectDisplayOnly = DetectDisplayOnly;
+
+  EfiBootManagerUpdateConsoleVariable (
+    ConIn,
+    (EFI_DEVICE_PATH_PROTOCOL *)&gUsbClassKeyboardDevicePath,
+    NULL
+    );
+
+  VisitAllInstancesOfProtocol (
+    &gEfiSerialIoProtocolGuid,
+    AddDevicePathForOneSerialIoInstance
+    );
+
+  Status = VisitAllInstancesOfProtocol (
+             &gEfiPciIoProtocolGuid,
+             DetectAndPreparePlatformPciDevicePath
+             );
+  return Status;
+}
+
+/**
+  The function will connect one root bridge
+
+  @param[in]  Handle     - The root bridge handle
+  @param[in]  Instance   - The instance of the root bridge
+
+  @return EFI_SUCCESS      Connect RootBridge successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+ConnectOneRootBridge (
+  IN EFI_HANDLE  Handle,
+  IN VOID        *Instance
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->ConnectController (Handle, NULL, NULL, FALSE);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Platform console init. Include the platform firmware vendor, revision
+  and so crc check.
+
+**/
+VOID
+EFIAPI
+PlatformConsoleInit (
+  VOID
+  )
+{
+  VisitAllInstancesOfProtocol (
+    &gEfiPciRootBridgeIoProtocolGuid,
+    ConnectOneRootBridge
+    );
+
+  //
+  // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+  //
+  DetectAndPreparePlatformPciDevicePaths (FALSE);
+}
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.h b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.h
new file mode 100644
index 0000000000..dc66db7ced
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformConsole.h
@@ -0,0 +1,69 @@
+/** @file
+Head file for BDS Platform specific code
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef PLATFORM_CONSOLE_H_
+#define PLATFORM_CONSOLE_H_
+
+#include <PiDxe.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Protocol/PciIo.h>
+
+#define IS_PCI_ISA_PDECODE(_p)  IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
+
+//
+// Type definitions
+//
+
+//
+// Platform Root Bridge
+//
+typedef struct {
+  ACPI_HID_DEVICE_PATH        PciRootBridge;
+  EFI_DEVICE_PATH_PROTOCOL    End;
+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
+
+typedef
+EFI_STATUS
+(EFIAPI *SIMPLE_PROTOCOL_INSTANCE_CALLBACK)(
+  IN EFI_HANDLE            Handle,
+  IN VOID                 *Instance
+  );
+
+/**
+  @param[in]  Handle - Handle of PCI device instance
+  @param[in]  PciIo - PCI IO protocol instance
+  @param[in]  Pci - PCI Header register block
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN PCI_TYPE00           *Pci
+  );
+
+/**
+  Platform console init. Include the platform firmware vendor, revision
+  and so crc check.
+
+**/
+VOID
+EFIAPI
+PlatformConsoleInit (
+  VOID
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformData.c b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformData.c
new file mode 100644
index 0000000000..d8871a4bd5
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/Capsule/PlatformBootManagerLib/PlatformData.c
@@ -0,0 +1,39 @@
+/** @file
+  Defined the platform specific device path which will be filled to
+  ConIn/ConOut variables.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "PlatformBootManager.h"
+
+///
+/// Predefined platform default console device path
+///
+GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[] = {
+  {
+    NULL,
+    0
+  }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED USB_CLASS_FORMAT_DEVICE_PATH  gUsbClassKeyboardDevicePath = {
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_USB_CLASS_DP,
+      {
+        (UINT8)(sizeof (USB_CLASS_DEVICE_PATH)),
+        (UINT8)((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
+      }
+    },
+    0xffff,           // VendorId
+    0xffff,           // ProductId
+    CLASS_HID,        // DeviceClass
+    SUBCLASS_BOOT,    // DeviceSubClass
+    PROTOCOL_KEYBOARD // DeviceProtocol
+  },
+  gEndEntire
+};
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
new file mode 100644
index 0000000000..2fd1ea45cd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
@@ -0,0 +1,115 @@
+## @file
+#  Capsule Runtime Driver produces two UEFI capsule runtime services: (UpdateCapsule, QueryCapsuleCapabilities).
+#
+#  It installs the Capsule Architectural Protocol defined in PI1.0a to signify
+#  the capsule runtime services are ready.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = CapsuleRuntimeDxe
+  MODULE_UNI_FILE                = CapsuleRuntimeDxe.uni
+  FILE_GUID                      = 42857F0A-13F2-4B21-8A23-53D3F714B840
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = CapsuleServiceInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC ARM AARCH64 RISCV64
+#
+
+[Sources]
+  CapsuleService.c
+  CapsuleService.h
+
+[Sources.Ia32, Sources.EBC, Sources.ARM, Sources.AARCH64, Sources.RISCV64]
+  SaveLongModeContext.c
+
+[Sources.Ia32, Sources.X64, Sources.ARM, Sources.AARCH64, Sources.RISCV64]
+  CapsuleCache.c
+
+[Sources.Ia32, Sources.X64, Sources.EBC, Sources.RISCV64]
+  CapsuleReset.c
+
+[Sources.ARM, Sources.AARCH64]
+  Arm/CapsuleReset.c
+
+[Sources.EBC]
+  CapsuleCacheNull.c
+
+[Sources.X64]
+  X64/SaveLongModeContext.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  PcdLib
+  DebugLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  CapsuleLib
+  UefiRuntimeLib
+  BaseLib
+  PrintLib
+  BaseMemoryLib
+  CacheMaintenanceLib
+  IoLib
+
+[LibraryClasses.X64]
+  UefiLib
+  BaseMemoryLib
+
+[Guids]
+  ## SOMETIMES_PRODUCES   ## Variable:L"CapsuleUpdateData" # (Process across reset capsule image) for capsule updated data
+  ## SOMETIMES_PRODUCES   ## Variable:L"CapsuleLongModeBuffer" # The long mode buffer used by IA32 Capsule PEIM to call X64 CapsuleCoalesce code to handle >4GB capsule blocks
+  gEfiCapsuleVendorGuid
+  gEfiFmpCapsuleGuid                            ## SOMETIMES_CONSUMES   ## GUID # FMP capsule GUID
+  gAmdSetCapsuleS3FlagGuid                      ## SOMETIMES_CONSUMES
+  gEfiEventVirtualAddressChangeGuid             ## CONSUMES
+
+[Protocols]
+  gEfiCapsuleArchProtocolGuid                   ## PRODUCES
+  gEfiMmCommunication2ProtocolGuid              ## CONSUMES
+
+[Protocols.X64]
+  ## UNDEFINED ## NOTIFY
+  ## SOMETIMES_CONSUMES
+  gEdkiiVariableLockProtocolGuid
+
+[FeaturePcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset        ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSupportProcessCapsuleAtRuntime   ## CONSUMES
+
+[FeaturePcd.X64]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode      ## CONSUMES
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule   ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule      ## SOMETIMES_CONSUMES # Populate Image requires reset support.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport         ## CONSUMES
+
+[Pcd.X64]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize   ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable                ## SOMETIMES_CONSUMES
+
+[Depex]
+  gEfiVariableWriteArchProtocolGuid AND            # Depends on variable write functionality to produce capsule data variable
+  gEfiMmCommunication2ProtocolGuid                 # Perform AMD Specific flags settings
+
+# [Hob.X64]
+# UNDEFINED                 ## SOMETIMES_CONSUMES # CPU
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  CapsuleRuntimeDxeExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
new file mode 100644
index 0000000000..6915c054dd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c
@@ -0,0 +1,461 @@
+/** @file
+  Capsule Runtime Driver produces two UEFI capsule runtime services.
+  (UpdateCapsule, QueryCapsuleCapabilities)
+  It installs the Capsule Architectural Protocol defined in PI1.0a to signify
+  the capsule runtime services are ready.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CapsuleService.h"
+
+#include <Library/IoLib.h>
+
+//
+// Handle for the installation of Capsule Architecture Protocol.
+//
+EFI_HANDLE  mNewHandle = NULL;
+
+//
+// The times of calling UpdateCapsule ()
+//
+UINTN  mTimes = 0;
+
+UINT32  mMaxSizePopulateCapsule    = 0;
+UINT32  mMaxSizeNonPopulateCapsule = 0;
+
+// Cached MM Communication protocol.
+EFI_MM_COMMUNICATION2_PROTOCOL  *mMmCommunication2 = NULL;
+
+// For MM Communication purpose.
+EFI_MM_COMMUNICATE_HEADER  *mCommunicationBuffer         = NULL;
+EFI_MM_COMMUNICATE_HEADER  *mCommunicationBufferPhysical = NULL;
+EFI_EVENT                  mVirtualAddressChangeEvent    = NULL;
+extern EFI_GUID            gAmdSetCapsuleS3FlagGuid;
+
+/**
+  Passes capsules to the firmware with both virtual and physical mapping. Depending on the intended
+  consumption, the firmware may process the capsule immediately. If the payload should persist
+  across a system reset, the reset value returned from EFI_QueryCapsuleCapabilities must
+  be passed into ResetSystem() and will cause the capsule to be processed by the firmware as
+  part of the reset process.
+
+  @param  CapsuleHeaderArray    Virtual pointer to an array of virtual pointers to the capsules
+                                being passed into update capsule.
+  @param  CapsuleCount          Number of pointers to EFI_CAPSULE_HEADER in
+                                CaspuleHeaderArray.
+  @param  ScatterGatherList     Physical pointer to a set of
+                                EFI_CAPSULE_BLOCK_DESCRIPTOR that describes the
+                                location in physical memory of a set of capsules.
+
+  @retval EFI_SUCCESS           Valid capsule was passed. If
+                                CAPSULE_FLAGS_PERSIT_ACROSS_RESET is not set, the
+                                capsule has been successfully processed by the firmware.
+  @retval EFI_DEVICE_ERROR      The capsule update was started, but failed due to a device error.
+  @retval EFI_INVALID_PARAMETER CapsuleSize is NULL, or an incompatible set of flags were
+                                set in the capsule header.
+  @retval EFI_INVALID_PARAMETER CapsuleCount is Zero.
+  @retval EFI_INVALID_PARAMETER For across reset capsule image, ScatterGatherList is NULL.
+  @retval EFI_UNSUPPORTED       CapsuleImage is not recognized by the firmware.
+  @retval EFI_OUT_OF_RESOURCES  When ExitBootServices() has been previously called this error indicates the capsule
+                                is compatible with this platform but is not capable of being submitted or processed
+                                in runtime. The caller may resubmit the capsule prior to ExitBootServices().
+  @retval EFI_OUT_OF_RESOURCES  When ExitBootServices() has not been previously called then this error indicates
+                                the capsule is compatible with this platform but there are insufficient resources to process.
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateCapsule (
+  IN EFI_CAPSULE_HEADER    **CapsuleHeaderArray,
+  IN UINTN                 CapsuleCount,
+  IN EFI_PHYSICAL_ADDRESS  ScatterGatherList OPTIONAL
+  )
+{
+  UINTN               ArrayNumber;
+  EFI_STATUS          Status;
+  EFI_CAPSULE_HEADER  *CapsuleHeader;
+  BOOLEAN             NeedReset;
+  BOOLEAN             InitiateReset;
+  CHAR16              CapsuleVarName[30];
+  CHAR16              *TempVarName;
+
+  //
+  // Check if platform support Capsule In RAM or not.
+  // Platform could choose to drop CapsulePei/CapsuleX64 and do not support Capsule In RAM.
+  //
+  if (!PcdGetBool (PcdCapsuleInRamSupport)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Capsule Count can't be less than one.
+  //
+  if (CapsuleCount < 1) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  NeedReset         = FALSE;
+  InitiateReset     = FALSE;
+  CapsuleHeader     = NULL;
+  CapsuleVarName[0] = 0;
+
+  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+    //
+    // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have
+    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
+    //
+    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must have
+    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
+    //
+    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Check FMP capsule flag
+    //
+    if (  CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)
+       && ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0))
+    {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Check Capsule image without populate flag by firmware support capsule function
+    //
+    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
+      Status = SupportCapsuleImage (CapsuleHeader);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+  }
+
+  //
+  // Walk through all capsules, record whether there is a capsule needs reset
+  // or initiate reset. And then process capsules which has no reset flag directly.
+  //
+  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+    //
+    // Here should be in the boot-time for non-reset capsule image
+    // Platform specific update for the non-reset capsule image.
+    //
+    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) == 0) {
+      if (EfiAtRuntime () && !FeaturePcdGet (PcdSupportProcessCapsuleAtRuntime)) {
+        Status = EFI_OUT_OF_RESOURCES;
+      } else {
+        Status = ProcessCapsuleImage (CapsuleHeader);
+      }
+
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    } else {
+      NeedReset = TRUE;
+      if ((CapsuleHeader->Flags & CAPSULE_FLAGS_INITIATE_RESET) != 0) {
+        InitiateReset = TRUE;
+      }
+    }
+  }
+
+  //
+  // After launching all capsules who has no reset flag, if no more capsules claims
+  // for a system reset just return.
+  //
+  if (!NeedReset) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // ScatterGatherList is only referenced if the capsules are defined to persist across
+  // system reset.
+  //
+  if (ScatterGatherList == (EFI_PHYSICAL_ADDRESS)(UINTN)NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check if the platform supports update capsule across a system reset
+  //
+  if (!IsPersistAcrossResetCapsuleSupported ()) {
+    return EFI_UNSUPPORTED;
+  }
+
+  CapsuleCacheWriteBack (ScatterGatherList);
+
+  //
+  // Construct variable name CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
+  // if user calls UpdateCapsule multiple times.
+  //
+  StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CHAR16), EFI_CAPSULE_VARIABLE_NAME);
+  TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
+  if (mTimes > 0) {
+    UnicodeValueToStringS (
+      TempVarName,
+      sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),
+      0,
+      mTimes,
+      0
+      );
+  }
+
+  //
+  // ScatterGatherList is only referenced if the capsules are defined to persist across
+  // system reset. Set its value into NV storage to let pre-boot driver to pick it up
+  // after coming through a system reset.
+  //
+  Status = EfiSetVariable (
+             CapsuleVarName,
+             &gEfiCapsuleVendorGuid,
+             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+             sizeof (UINTN),
+             (VOID *)&ScatterGatherList
+             );
+  if (!EFI_ERROR (Status)) {
+    //
+    // Variable has been set successfully, increase variable index.
+    //
+    mTimes++;
+    if (InitiateReset) {
+      //
+      // Firmware that encounters a capsule which has the CAPSULE_FLAGS_INITIATE_RESET Flag set in its header
+      // will initiate a reset of the platform which is compatible with the passed-in capsule request and will
+      // not return back to the caller.
+      //
+      // EfiResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+      // Invoke AMD Specific S3.
+      DEBUG ((DEBUG_INFO, "Setting AMD Specific S3 Flag.\n"));
+      Status = mMmCommunication2->Communicate (
+                                    mMmCommunication2,
+                                    mCommunicationBufferPhysical,
+                                    mCommunicationBuffer,
+                                    NULL
+                                    );
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Returns if the capsule can be supported via UpdateCapsule().
+  Notice: When PcdCapsuleInRamSupport is unsupported, even this routine returns a valid answer,
+  the capsule still is unsupported via UpdateCapsule().
+
+  @param  CapsuleHeaderArray    Virtual pointer to an array of virtual pointers to the capsules
+                                being passed into update capsule.
+  @param  CapsuleCount          Number of pointers to EFI_CAPSULE_HEADER in
+                                CaspuleHeaderArray.
+  @param  MaxiumCapsuleSize     On output the maximum size that UpdateCapsule() can
+                                support as an argument to UpdateCapsule() via
+                                CapsuleHeaderArray and ScatterGatherList.
+  @param  ResetType             Returns the type of reset required for the capsule update.
+
+  @retval EFI_SUCCESS           Valid answer returned.
+  @retval EFI_UNSUPPORTED       The capsule image is not supported on this platform, and
+                                MaximumCapsuleSize and ResetType are undefined.
+  @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL, or ResetTyep is NULL,
+                                Or CapsuleCount is Zero, or CapsuleImage is not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+QueryCapsuleCapabilities (
+  IN  EFI_CAPSULE_HEADER  **CapsuleHeaderArray,
+  IN  UINTN               CapsuleCount,
+  OUT UINT64              *MaxiumCapsuleSize,
+  OUT EFI_RESET_TYPE      *ResetType
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               ArrayNumber;
+  EFI_CAPSULE_HEADER  *CapsuleHeader;
+  BOOLEAN             NeedReset;
+
+  //
+  // Capsule Count can't be less than one.
+  //
+  if (CapsuleCount < 1) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check whether input parameter is valid
+  //
+  if ((MaxiumCapsuleSize == NULL) || (ResetType == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CapsuleHeader = NULL;
+  NeedReset     = FALSE;
+
+  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+    //
+    // A capsule which has the CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flag must have
+    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
+    //
+    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // A capsule which has the CAPSULE_FLAGS_INITIATE_RESET flag must have
+    // CAPSULE_FLAGS_PERSIST_ACROSS_RESET set in its header as well.
+    //
+    if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET)) == CAPSULE_FLAGS_INITIATE_RESET) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Check FMP capsule flag
+    //
+    if (  CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiFmpCapsuleGuid)
+       && ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0))
+    {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Check Capsule image without populate flag is supported by firmware
+    //
+    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
+      Status = SupportCapsuleImage (CapsuleHeader);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+  }
+
+  //
+  // Find out whether there is any capsule defined to persist across system reset.
+  //
+  for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
+    CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
+    if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
+      NeedReset = TRUE;
+      break;
+    }
+  }
+
+  if (NeedReset) {
+    //
+    // Check if the platform supports update capsule across a system reset
+    //
+    if (!IsPersistAcrossResetCapsuleSupported ()) {
+      return EFI_UNSUPPORTED;
+    }
+
+    *ResetType         = EfiResetWarm;
+    *MaxiumCapsuleSize = (UINT64)mMaxSizePopulateCapsule;
+  } else {
+    //
+    // For non-reset capsule image.
+    //
+    *ResetType         = EfiResetCold;
+    *MaxiumCapsuleSize = (UINT64)mMaxSizeNonPopulateCapsule;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+
+  Here it converts the SMM Communicate buffer address into virtual.
+
+  @param[in]  Event        Event whose notification function is being invoked.
+  @param[in]  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+VariableAddressChangeEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EfiConvertPointer (0x0, (VOID **)&mCommunicationBuffer);
+  EfiConvertPointer (0x0, (VOID **)&mMmCommunication2);
+}
+
+/**
+
+  This code installs UEFI capsule runtime service.
+
+  @param  ImageHandle    The firmware allocated handle for the EFI image.
+  @param  SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS    UEFI Capsule Runtime Services are installed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+CapsuleServiceInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  mMaxSizePopulateCapsule    = PcdGet32 (PcdMaxSizePopulateCapsule);
+  mMaxSizeNonPopulateCapsule = PcdGet32 (PcdMaxSizeNonPopulateCapsule);
+
+  //
+  // When PEI phase is IA32, DXE phase is X64, it is possible that capsule data are
+  // put above 4GB, so capsule PEI will transfer to long mode to get capsule data.
+  // The page table and stack is used to transfer processor mode from IA32 to long mode.
+  // Create the base address of page table and stack, and save them into variable.
+  // This is not needed when capsule with reset type is not supported.
+  //
+  SaveLongModeContext ();
+
+  //
+  // Install capsule runtime services into UEFI runtime service tables.
+  //
+  gRT->UpdateCapsule            = UpdateCapsule;
+  gRT->QueryCapsuleCapabilities = QueryCapsuleCapabilities;
+
+  //
+  // Install the Capsule Architectural Protocol on a new handle
+  // to signify the capsule runtime services are ready.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mNewHandle,
+                  &gEfiCapsuleArchProtocolGuid,
+                  NULL,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL, (VOID **)&mMmCommunication2);
+  ASSERT_EFI_ERROR (Status);
+  Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof (EFI_MM_COMMUNICATE_HEADER), (VOID **)&mCommunicationBufferPhysical);
+  ASSERT_EFI_ERROR (Status);
+  CopyGuid (&(mCommunicationBufferPhysical->HeaderGuid), &gAmdSetCapsuleS3FlagGuid);
+  mCommunicationBufferPhysical->MessageLength = 0;
+  mCommunicationBuffer                        = mCommunicationBufferPhysical;
+
+  // Create an event to update SMM pointers.
+  gBS->CreateEventEx (
+         EVT_NOTIFY_SIGNAL,
+         TPL_NOTIFY,
+         VariableAddressChangeEvent,
+         NULL,
+         &gEfiEventVirtualAddressChangeGuid,
+         &mVirtualAddressChangeEvent
+         );
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h
new file mode 100644
index 0000000000..71f00c2045
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h
@@ -0,0 +1,73 @@
+/** @file
+  Capsule Runtime Driver produces two UEFI capsule runtime services.
+  (UpdateCapsule, QueryCapsuleCapabilities)
+  It installs the Capsule Architectural Protocol defined in PI1.0a to signify
+  the capsule runtime services are ready.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CAPSULE_SERVICE_H_
+#define CAPSULE_SERVICE_H_
+
+#include <Uefi.h>
+
+#include <Protocol/Capsule.h>
+#include <Protocol/MmCommunication2.h>
+#include <Guid/CapsuleVendor.h>
+#include <Guid/FmpCapsule.h>
+#include <Guid/EventGroup.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/CapsuleLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseMemoryLib.h>
+
+/**
+  Create the variable to save the base address of page table and stack
+  for transferring into long mode in IA32 PEI.
+**/
+VOID
+SaveLongModeContext (
+  VOID
+  );
+
+/**
+  Whether the platform supports capsules that persist across reset. Note that
+  some platforms only support such capsules at boot time.
+
+  @return TRUE  if a PersistAcrossReset capsule may be passed to UpdateCapsule()
+                at this time
+          FALSE otherwise
+**/
+BOOLEAN
+IsPersistAcrossResetCapsuleSupported (
+  VOID
+  );
+
+/**
+  Writes Back a range of data cache lines covering a set of capsules in memory.
+
+  Writes Back the data cache lines specified by ScatterGatherList.
+
+  @param  ScatterGatherList Physical address of the data structure that
+                            describes a set of capsules in memory
+
+**/
+VOID
+CapsuleCacheWriteBack (
+  IN  EFI_PHYSICAL_ADDRESS  ScatterGatherList
+  );
+
+#endif
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114581): https://edk2.groups.io/g/devel/message/114581
Mute This Topic: https://groups.io/mt/103975444/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 04/32] AMD/VanGoghBoard: Check in AgesaPublicPkg
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (2 preceding siblings ...)
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 03/32] AMD/VanGoghBoard: Check in Capsule update Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:10 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 05/32] AMD/VanGoghBoard: Check in PlatformSecLib Zhai, MingXin (Duke) via groups.io
                   ` (28 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:10 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Chachani board platform code depends on some AGESA-related PCDs/GUIDs.
  Add AgesaPublicPkg for AGESA-related PCDs/GUIDs to support platfrom build.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../VanGoghBoard/AgesaPublic/AgesaPublic.dec  |  61 +++++
 .../VanGoghBoard/AgesaPublic/Include/AGESA.h  |  35 +++
 .../VanGoghBoard/AgesaPublic/Include/AMD.h    | 189 +++++++++++++
 .../AgesaPublic/Include/AmdPspDirectory.h     |  55 ++++
 .../AgesaPublic/Include/FchRegistersCommon.h  |  23 ++
 .../Include/Guid/AmdMemoryInfoHob.h           |  51 ++++
 .../Include/Library/AmdPspBaseLibV2.h         | 248 ++++++++++++++++++
 .../Include/Library/AmdPspCommonLib.h         |  29 ++
 .../Include/Library/AmdPspFtpmLib.h           |  94 +++++++
 .../AgesaPublic/Include/Ppi/AmdPspFtpmPpi.h   |  80 ++++++
 .../Include/Protocol/AmdPspFtpmProtocol.h     | 112 ++++++++
 11 files changed, 977 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/AgesaPublic.dec
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/AGESA.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/AMD.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/AmdPspDirectory.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/FchRegistersCommon.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Guid/AmdMemoryInfoHob.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspBaseLibV2.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspCommonLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspFtpmLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Ppi/AmdPspFtpmPpi.h
 create mode 100644 Platform/AMD/VanGoghBoard/AgesaPublic/Include/Protocol/AmdPspFtpmProtocol.h

diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/AgesaPublic.dec b/Platform/AMD/VanGoghBoard/AgesaPublic/AgesaPublic.dec
new file mode 100644
index 0000000000..e987b9b603
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/AgesaPublic.dec
@@ -0,0 +1,61 @@
+## @file
+# EDK II AgesaPublic.dec file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010005
+  PACKAGE_NAME                   = AgesaPublic
+  PACKAGE_GUID                   = EA54B0FA-908C-43DE-95A5-5E821A893CA4
+  PACKAGE_VERSION                = 0.1
+
+[Includes]
+  Include
+
+[Guids]
+  gEfiAmdAgesaModulePkgTokenSpaceGuid      = { 0x7788adf0, 0x9788, 0x4a3f, { 0x83, 0xfa, 0xcb, 0x51, 0x2e, 0x7c, 0xf8, 0xdd } }
+  gEfiAmdAgesaPkgTokenSpaceGuid            = { 0xd4d8435f, 0xfffb, 0x4acb, { 0xa0, 0x4d, 0xff, 0x0f, 0xad, 0x67, 0x7f, 0xe9 } }
+  gAmdCpmPkgTokenSpaceGuid                 = { 0x916e0ddd, 0x2bd2, 0x4704, { 0x93, 0xb9, 0x59, 0x4b, 0x01, 0xa5, 0xfa, 0x9f } }
+  gAmdResourceSizeForEachRbGuid            = { 0x542b8f2f, 0xbd52, 0x4233, { 0x8c, 0x3d, 0x66, 0x53, 0x0d, 0xe8, 0xa3, 0x69 } }
+  gAmdPbsSystemConfigurationGuid           = { 0xa339d746, 0xf678, 0x49b3, { 0x9f, 0xc7, 0x54, 0xce, 0x0f, 0x9d, 0xf2, 0x26 } }
+  gAmdTotalNumberOfRootBridgesGuid         = { 0xfb5703f5, 0xf8a7, 0xf401, { 0x18, 0xb4, 0x3f, 0x10, 0x8d, 0xeb, 0x26, 0x12 } }
+  gApSyncFlagNvVariableGuid                = { 0xad3f6761, 0xf0a3, 0x46c8, { 0xa4, 0xcb, 0x19, 0xb7, 0x0f, 0xfd, 0xb3, 0x05 } }
+  gAmdMemoryInfoHobGuid                    = { 0x1bce3d14, 0xa5fe, 0x4a0b, { 0x9a, 0x8d, 0x69, 0xca, 0x5d, 0x98, 0x38, 0xd3 } }
+  gAmdPspApobHobGuid                       = { 0x30b174f3, 0x7712, 0x4cca, { 0xbd, 0x13, 0xd0, 0xb8, 0xa8, 0x80, 0x19, 0x97 } }
+
+[Protocols]
+  gPspFlashAccSmmCommReadyProtocolGuid     = { 0x9f373486, 0xda76, 0x4c9f, { 0x81, 0x55, 0x6c, 0xcd, 0xdb, 0x0b, 0x0b, 0x04 } }
+  gAmdPspFtpmProtocolGuid                  = { 0xac234e04, 0xb036, 0x476c, { 0x91, 0x66, 0xbe, 0x47, 0x52, 0xa0, 0x95, 0x09 } }
+  gFchInitDonePolicyProtocolGuid           = { 0xc63c0c73, 0xf612, 0x4c02, { 0x84, 0xa3, 0xc6, 0x40, 0xad, 0x0b, 0xa6, 0x22 } }
+  gAmdCapsuleSmmHookProtocolGuid           = { 0x4fc43bbe, 0x1433, 0x4951, { 0xac, 0x2d, 0x0d, 0x01, 0xfe, 0xc0, 0x0e, 0xb1 } }
+  gAmdCpmAllPciIoProtocolsInstalledProtocolGuid = { 0x676D7012, 0x139B, 0x485A, { 0x96, 0xF1, 0x98, 0x6F, 0xC4, 0x8A, 0x86, 0x4B } }
+  gAmdFspSetupTableInitDoneGuid            = { 0xef5394c6, 0x566d, 0x440f, { 0x9d, 0x05, 0xc0, 0xa3, 0x2c, 0xb9, 0x33, 0x58 } }
+
+[Ppis]
+  gAmdMemoryInfoHobPpiGuid                 = { 0xba16e587, 0x1d66, 0x41b7, { 0x9b, 0x52, 0xca, 0x4f, 0x2c, 0xad, 0x0d, 0xc8 } }
+  gAmdPspFtpmPpiGuid                       = { 0x91774185, 0xf72d, 0x467e, { 0x93, 0x39, 0xe0, 0x08, 0xdb, 0xae, 0x0e, 0x14 } }
+  gAmdPspFtpmFactoryResetPpiGuid           = { 0x9c98130a, 0x8921, 0x45eb, { 0x86, 0xf3, 0x16, 0x04, 0x35, 0xc7, 0xc6, 0x40 } }
+  gCapsuleUpdateDetectedPpiGuid            = { 0x745dfc73, 0xc401, 0x4ced, { 0x8d, 0x3b, 0x1a, 0x82, 0xf3, 0xda, 0xdc, 0xf8 } }
+  gAmdCpmTablePpiGuid                      = { 0xd71cf893, 0xa8b5, 0x49d3, { 0xa2, 0x1b, 0x31, 0xe2, 0xf5, 0xc4, 0xa7, 0x47 } }
+
+[PcdsFixedAtBuild]
+  gEfiAmdAgesaPkgTokenSpaceGuid.PcdFchOemBeforePciRestoreSwSmi|0xEA|UINT8|0x0002F010
+  gEfiAmdAgesaPkgTokenSpaceGuid.PcdFchOemAfterPciRestoreSwSmi|0xD4|UINT8|0x0002F011
+  gEfiAmdAgesaPkgTokenSpaceGuid.PcdAmdFchCfgAcpiPmTmrBlkAddr|0x408|UINT16|0x0002F006
+  gAmdCpmPkgTokenSpaceGuid.AcpiRestoreSwSmi|0xE3|UINT8|0x00000040
+
+[PcdsDynamicEx]
+  ## Common
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdS3LibPrivateDataAddress|0|UINT64|0x00027000
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdSmmCommunicationAddress|0|UINT64|0x00027001
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdS3LibTableAddress|0|UINT64|0x00027002
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdS3LibTableSize|0x4000|UINT64|0x00027003
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdFabricResourceDefaultSizePtr|0|UINT64|0x00DF0000
+
+  ## Setup solution
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdFspSetupTableInitNeedsReset|FALSE|BOOLEAN|0xFE000000
+  #Note: system TPM config, SBIOS needs to set the value in PEI phase
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdPspSystemTpmConfig|0x1|UINT8|0x00040024
+  gEfiAmdAgesaPkgTokenSpaceGuid.PcdAmdFchCfgSmiCmdPortAddr|0xB0|UINT16|0x0003FFC0
\ No newline at end of file
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/AGESA.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/AGESA.h
new file mode 100644
index 0000000000..da399e3968
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/AGESA.h
@@ -0,0 +1,35 @@
+/** @file
+     Common AMD header file
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AGESA_H_
+#define AGESA_H_
+
+#include  "AMD.h"
+
+///< CPU MSR Register definitions ------------------------------------------
+#define SYS_CFG   0xC0010010ul
+#define TOP_MEM   0xC001001Aul
+#define TOP_MEM2  0xC001001Dul
+#define HWCR      0xC0010015ul
+#define NB_CFG    0xC001001Ful
+
+// CPU Build Configuration structures and definitions
+
+#define AMD_AP_MTRR_FIX64k_00000  0x00000250ul
+#define AMD_AP_MTRR_FIX16k_80000  0x00000258ul
+#define AMD_AP_MTRR_FIX16k_A0000  0x00000259ul
+#define AMD_AP_MTRR_FIX4k_C0000   0x00000268ul
+#define AMD_AP_MTRR_FIX4k_C8000   0x00000269ul
+#define AMD_AP_MTRR_FIX4k_D0000   0x0000026Aul
+#define AMD_AP_MTRR_FIX4k_D8000   0x0000026Bul
+#define AMD_AP_MTRR_FIX4k_E0000   0x0000026Cul
+#define AMD_AP_MTRR_FIX4k_E8000   0x0000026Dul
+#define AMD_AP_MTRR_FIX4k_F0000   0x0000026Eul
+#define AMD_AP_MTRR_FIX4k_F8000   0x0000026Ful
+#define CPU_LIST_TERMINAL         0xFFFFFFFFul
+
+#endif // AGESA_H_
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/AMD.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/AMD.h
new file mode 100644
index 0000000000..f604e5cd78
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/AMD.h
@@ -0,0 +1,189 @@
+/** @file
+     Common AMD header file
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AMD_H_
+#define AMD_H_
+
+/// The return status for all AGESA public services.
+///
+/// Services return the most severe status of any logged event.  Status other than SUCCESS, UNSUPPORTED, and BOUNDS_CHK
+/// will have log entries with more detail.
+///
+typedef enum {
+  AGESA_SUCCESS = 0,            ///< 0 -The service completed normally. Info may be logged.
+  AGESA_UNSUPPORTED,            ///< 1 - The dispatcher or create struct had an unimplemented function requested.
+  ///<      Not logged.
+  AGESA_BOUNDS_CHK,             ///< 2 - A dynamic parameter was out of range and the service was not provided.
+  ///<      Example, memory address not installed, heap buffer handle not found.
+  ///<      Not Logged.
+  AGESA_SYNC_MORE_DATA,     ///< 3 - More data is available from PSP communications
+  AGESA_SYNC_SLAVE_ASSERT,  ///< 4 - Slave is at an ASSERT (used in ABL)
+  // AGESA_STATUS of greater severity (the ones below this line), always have a log entry available.
+  AGESA_ALERT,                     ///< 5 - An observed condition, but no loss of function.  See Log.
+  AGESA_WARNING,                   ///< 6 - Possible or minor loss of function.  See Log.
+  AGESA_ERROR,                     ///< 7 - Significant loss of function, boot may be possible.  See Log.
+  AGESA_CRITICAL,                  ///< 8 - Continue boot only to notify user.  See Log.
+  AGESA_FATAL,                     ///< 9 - Halt booting.  See Log, however Fatal errors pertaining to heap problems
+  ///<      may not be able to reliably produce log events.
+  AGESA_OC_FATAL,                 ///< 10 - Halt booting.  Critical Memory Overclock failure.
+  AGESA_SKIP_ERROR,               ///< 11 - Error, Skip init steps.
+  AgesaStatusMax                  ///< Not a status, for limit checking.
+} AGESA_STATUS;
+
+/// For checking whether a status is at or above the mandatory log level.
+#define AGESA_STATUS_LOG_LEVEL  AGESA_ALERT
+
+/**
+ * Callout method to the host environment.
+ *
+ * Callout using a dispatch with appropriate thunk layer, which is determined by the host environment.
+ *
+ * @param[in]        Function      The specific callout function being invoked.
+ * @param[in]        FcnData       Function specific data item.
+ * @param[in,out]    ConfigPtr     Reference to Callout params.
+ */
+typedef AGESA_STATUS (*CALLOUT_ENTRY) (
+  IN       UINT32  Function,
+  IN       UINTN   FcnData,
+  IN OUT   VOID    *ConfigPtr
+  );
+
+typedef AGESA_STATUS (*IMAGE_ENTRY) (
+  VOID  *ConfigPtr
+  );
+typedef AGESA_STATUS (*MODULE_ENTRY) (
+  VOID  *ConfigPtr
+  );
+
+/// This allocation type is used by the AmdCreateStruct entry point
+typedef enum {
+  PreMemHeap = 0,                                           ///< Create heap in cache.
+  PostMemDram,                                              ///< Create heap in memory.
+  ByHost                                                    ///< Create heap by Host.
+} ALLOCATION_METHOD;
+
+/// These width descriptors are used by the library function, and others, to specify the data size
+typedef enum ACCESS_WIDTH {
+  AccessWidthNone = 0,                                      ///< dummy access width
+  AccessWidth8    = 1,                                      ///< Access width is 8 bits.
+  AccessWidth16,                                            ///< Access width is 16 bits.
+  AccessWidth32,                                            ///< Access width is 32 bits.
+  AccessWidth64,                                            ///< Access width is 64 bits.
+
+  AccessS3SaveWidth8 = 0x81,                                ///< Save 8 bits data.
+  AccessS3SaveWidth16,                                      ///< Save 16 bits data.
+  AccessS3SaveWidth32,                                      ///< Save 32 bits data.
+  AccessS3SaveWidth64,                                      ///< Save 64 bits data.
+} ACCESS_WIDTH;
+
+/// AGESA struct name
+typedef enum {
+  // AGESA BASIC FUNCTIONS
+  AMD_INIT_RECOVERY = 0x00020000,                           ///< AmdInitRecovery entry point handle
+  AMD_CREATE_STRUCT,                                        ///< AmdCreateStruct handle
+  AMD_INIT_EARLY,                                           ///< AmdInitEarly entry point handle
+  AMD_INIT_ENV,                                             ///< AmdInitEnv entry point handle
+  AMD_INIT_LATE,                                            ///< AmdInitLate entry point handle
+  AMD_INIT_MID,                                             ///< AmdInitMid entry point handle
+  AMD_INIT_POST,                                            ///< AmdInitPost entry point handle
+  AMD_INIT_RESET,                                           ///< AmdInitReset entry point handle
+  AMD_INIT_RESUME,                                          ///< AmdInitResume entry point handle
+  AMD_RELEASE_STRUCT,                                       ///< AmdReleaseStruct handle
+  AMD_S3LATE_RESTORE,                                       ///< AmdS3LateRestore entry point handle
+  AMD_GET_APIC_ID,                                          ///< AmdGetApicId entry point handle
+  AMD_GET_PCI_ADDRESS,                                      ///< AmdGetPciAddress entry point handle
+  AMD_IDENTIFY_CORE,                                        ///< AmdIdentifyCore general service handle
+  AMD_READ_EVENT_LOG,                                       ///< AmdReadEventLog general service handle
+  AMD_GET_EXECACHE_SIZE,                                    ///< AmdGetAvailableExeCacheSize general service handle
+  AMD_LATE_RUN_AP_TASK,                                     ///< AmdLateRunApTask entry point handle
+  AMD_IDENTIFY_DIMMS,                                       ///< AmdIdentifyDimm general service handle
+  AMD_GET_2D_DATA_EYE,                                      ///< AmdGet2DDataEye general service handle
+  AMD_S3FINAL_RESTORE,                                      ///< AmdS3FinalRestore entry point handle
+  AMD_INIT_RTB                                              ///< AmdInitRtb entry point handle
+} AGESA_STRUCT_NAME;
+
+// AGESA Structures
+
+/// The standard header for all AGESA services.
+/// For internal AGESA naming conventions, see @ref amdconfigparamname .
+typedef struct {
+  IN       UINT32           ImageBasePtr;           ///< The AGESA Image base address.
+  IN       UINT32           Func;                   ///< The service desired
+  IN       UINT32           AltImageBasePtr;        ///< Alternate Image location
+  IN       CALLOUT_ENTRY    CalloutPtr;             ///< For Callout from AGESA
+  IN       UINT8            HeapStatus;             ///< For heap status from boot time slide.
+  IN       UINT64           HeapBasePtr;            ///< Location of the heap
+  IN OUT   UINT8            Reserved[7];            ///< This space is reserved for future use.
+} AMD_CONFIG_PARAMS;
+
+/// Create Struct Interface.
+typedef struct {
+  IN       AMD_CONFIG_PARAMS    StdHeader;         ///< Standard configuration header
+  IN       AGESA_STRUCT_NAME    AgesaFunctionName; ///< The service to init
+  IN       ALLOCATION_METHOD    AllocationMethod;  ///< How to handle buffer allocation
+  IN OUT   UINT32               NewStructSize;     ///< The size of the allocated data, in for ByHost, else out only.
+  IN OUT   VOID                 *NewStructPtr;     ///< The struct for the service.
+                                                   ///< The struct to init for ByHost allocation,
+                                                   ///< the initialized struct on return.
+} AMD_INTERFACE_PARAMS;
+
+/// AGESA Binary module header structure
+typedef struct {
+  IN  UINT32    Signature;                        ///< Binary Signature
+  IN  CHAR8     CreatorID[8];                     ///< 8 characters ID
+  IN  CHAR8     Version[12];                      ///< 12 characters version
+  IN  UINT32    ModuleInfoOffset;                 ///< Offset of module
+  IN  UINT32    EntryPointAddress;                ///< Entry address
+  IN  UINT32    ImageBase;                        ///< Image base
+  IN  UINT32    RelocTableOffset;                 ///< Relocate Table offset
+  IN  UINT32    ImageSize;                        ///< Size
+  IN  UINT16    Checksum;                         ///< Checksum
+  IN  UINT8     ImageType;                        ///< Type
+  IN  UINT8     V_Reserved;                       ///< Reserved
+} AMD_IMAGE_HEADER;
+
+/// AGESA Binary module header structure
+typedef struct _AMD_MODULE_HEADER {
+  IN  UINT32                       ModuleHeaderSignature; ///< Module signature
+  IN  CHAR8                        ModuleIdentifier[8];   ///< 8 characters ID
+  IN  CHAR8                        ModuleVersion[12];     ///< 12 characters version
+  IN  VOID                         *ModuleDispatcher;     ///< A pointer point to dispatcher
+  IN  struct _AMD_MODULE_HEADER    *NextBlock;            ///< Next module header link
+} AMD_MODULE_HEADER;
+
+/// AGESA_CODE_SIGNATURE
+typedef struct {
+  IN  CHAR8    Signature[8];                      ///< code header Signature
+  IN  CHAR8    ComponentName[16];                 ///< 16 character name of the code module
+  IN  CHAR8    Version[12];                       ///< 12 character version string
+  IN  CHAR8    TerminatorNull;                    ///< null terminated string
+  IN  CHAR8    VerReserved[7];                    ///< reserved space
+} AMD_CODE_HEADER;
+
+//   SBDFO - Segment Bus Device Function Offset
+//   31:28   Segment (4-bits)
+//   27:20   Bus     (8-bits)
+//   19:15   Device  (5-bits)
+//   14:12   Function(3-bits)
+//   11:00   Offset  (12-bits)
+
+#define MAKE_SBDFO(Seg, Bus, Dev, Fun, Off)  ((((UINT32) (Seg)) << 28) | (((UINT32) (Bus)) << 20) |\
+                   (((UINT32)(Dev)) << 15) | (((UINT32)(Fun)) << 12) | ((UINT32)(Off)))
+#define ILLEGAL_SBDFO  0xFFFFFFFFul
+
+/// CPUID data received registers format
+typedef struct {
+  OUT UINT32    EAX_Reg;                          ///< CPUID instruction result in EAX
+  OUT UINT32    EBX_Reg;                          ///< CPUID instruction result in EBX
+  OUT UINT32    ECX_Reg;                          ///< CPUID instruction result in ECX
+  OUT UINT32    EDX_Reg;                          ///< CPUID instruction result in EDX
+} CPUID_DATA;
+
+// Topology Services definitions and macros
+#define TOPOLOGY_LIST_TERMINAL  0xFF                        ///< End of list.
+
+#endif // AMD_H_
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/AmdPspDirectory.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/AmdPspDirectory.h
new file mode 100644
index 0000000000..fcb1c55638
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/AmdPspDirectory.h
@@ -0,0 +1,55 @@
+/** @file
+    AMD Psp Directory header file
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AMD_PSP_DIR_H_
+#define AMD_PSP_DIR_H_
+
+#pragma pack (push, 1)
+#define PSP_DIRECTORY_HEADER_SIGNATURE      0x50535024ul ///< $PSP
+#define PSP_LV2_DIRECTORY_HEADER_SIGNATURE  0x324C5024ul ///< $PL2
+/// Define structure for PSP directory
+typedef struct {
+  UINT32    Cookie;       ///< "$PSP"
+  UINT32    Checksum;     ///< 32 bit CRC of header items below and the entire table
+  UINT32    TotalEntries; ///< Number of PSP Entries
+  UINT32    Reserved;     ///< Unused
+} PSP_DIRECTORY_HEADER;
+
+typedef struct {
+  UINT32    Type       : 8;  ///< Type of PSP Directory entry
+  UINT32    SubProgram : 8;  ///< Specify the SubProgram
+  UINT32    RomId      : 2;  ///< Specify the ROM ID
+  UINT32    Reserved   : 14; ///< Reserved
+} PSP_DIRECTORY_ENTRY_TYPE_FIELD;
+
+typedef union {
+  PSP_DIRECTORY_ENTRY_TYPE_FIELD    Field; // Definition of each filed
+  UINT32                            Value; // Group it as 32bits Int
+} PSP_DIRECTORY_ENTRY_TYPE;
+
+enum _PSP_DIRECTORY_ENTRY_TYPE {
+  PSP_REGION_A_DIR = 0x48,                          ///< PSP entry points to PSP DIR in Region A
+  PSP_REGION_B_DIR = 0x4A,                          ///< PSP entry points to PSP DIR in Region B
+};
+
+/// Structure for PSP Entry
+typedef struct {
+  PSP_DIRECTORY_ENTRY_TYPE    Type;       ///< Type of PSP entry; 32 bit long
+  UINT32                      Size;       ///< Size of PSP Entry in bytes
+  UINT64                      Location;   ///< Location of PSP Entry (byte offset from start of SPI-ROM)
+} PSP_DIRECTORY_ENTRY;
+
+/// Structure for PSP directory
+typedef struct {
+  PSP_DIRECTORY_HEADER    Header;         ///< PSP directory header
+  PSP_DIRECTORY_ENTRY     PspEntry[1];    ///< Array of PSP entries each pointing to a binary in SPI flash
+                                          ///< The actual size of this array comes from the
+                                          ///< header (PSP_DIRECTORY.Header.TotalEntries)
+} PSP_DIRECTORY;
+
+#pragma pack (pop)
+#endif //AMD_PSP_DIR_H_
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/FchRegistersCommon.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/FchRegistersCommon.h
new file mode 100644
index 0000000000..a69a4791cd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/FchRegistersCommon.h
@@ -0,0 +1,23 @@
+/** @file
+  Implements FchRegistersCommon.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#define R_FCH_ACPI_PM1_STATUS  0x00
+#define R_FCH_ACPI_PM1_ENABLE  0x02
+#define R_FCH_ACPI_PM_CONTROL  0x04
+#define ACPI_MMIO_BASE         0xFED80000ul
+#define SMI_BASE               0x200          // DWORD
+#define PMIO_BASE              0x300          // DWORD
+#define FCH_SMI_REG80          0x80           // SmiStatus0
+#define FCH_SMI_REG84          0x84           // SmiStatus1
+#define FCH_SMI_REG88          0x88           // SmiStatus2
+#define FCH_SMI_REG8C          0x8C           // SmiStatus3
+#define FCH_SMI_REG90          0x90           // SmiStatus4
+#define FCH_SMI_REG98          0x98           // SmiTrig
+#define FCH_SMI_REGA0          0xA0
+#define FCH_SMI_REGB0          0xB0
+#define FCH_SMI_REGC4          0xC4
+#define FCH_PMIOA_REG60        0x60           // AcpiPm1EvtBlk
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Guid/AmdMemoryInfoHob.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Guid/AmdMemoryInfoHob.h
new file mode 100644
index 0000000000..44b8dd9b4f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Guid/AmdMemoryInfoHob.h
@@ -0,0 +1,51 @@
+/** @file
+     AMD Memory Info Hob Definition
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AMD_MEMORY_INFO_HOB_H_
+#define AMD_MEMORY_INFO_HOB_H_
+
+extern EFI_GUID  gAmdMemoryInfoHobGuid;
+
+#pragma pack (push, 1)
+
+/// Memory descriptor structure for each memory rang
+typedef struct {
+  UINT64    Base;                           ///< Base address of memory rang
+  UINT64    Size;                           ///< Size of memory rang
+  UINT32    Attribute;                      ///< Attribute of memory rang
+  UINT32    Reserved;                       ///< For alignment purpose
+} AMD_MEMORY_RANGE_DESCRIPTOR;
+
+#define AMD_MEMORY_ATTRIBUTE_AVAILABLE             0x1
+#define AMD_MEMORY_ATTRIBUTE_UMA                   0x2
+#define AMD_MEMORY_ATTRIBUTE_MMIO                  0x3
+#define AMD_MEMORY_ATTRIBUTE_RESERVED              0x4
+#define AMD_MEMORY_ATTRIBUTE_GPUMEM                0x5
+#define AMD_MEMORY_ATTRIBUTE_GPU_SP                0x6
+#define AMD_MEMORY_ATTRIBUTE_GPU_RESERVED          0x7
+#define AMD_MEMORY_ATTRIBUTE_GPU_RESERVED_TMR      0x8
+#define AMD_MEMORY_ATTRIBUTE_Reserved_SmuFeatures  0x9
+
+/// Memory info HOB structure
+typedef struct  {
+  UINT32                         Version;                 ///< Version of HOB structure
+  BOOLEAN                        AmdMemoryVddioValid;     ///< This field determines if Vddio is valid
+  UINT16                         AmdMemoryVddio;          ///< Vddio Voltage
+  BOOLEAN                        AmdMemoryVddpVddrValid;  ///< This field determines if VddpVddr is valid
+  UINT8                          AmdMemoryVddpVddr;       ///< VddpVddr voltage
+  BOOLEAN                        AmdMemoryFrequencyValid; ///< Memory Frequency Valid
+  UINT32                         AmdMemoryFrequency;      ///< Memory Frquency
+  UINT32                         AmdMemoryDdrMaxRate;     ///< Memory DdrMaxRate
+  UINT32                         NumberOfDescriptor;      ///< Number of memory range descriptor
+  AMD_MEMORY_RANGE_DESCRIPTOR    Ranges[1];               ///< Memory ranges array
+} AMD_MEMORY_INFO_HOB;
+
+#pragma pack (pop)
+
+#define AMD_MEMORY_INFO_HOB_VERISION  0x00000110ul        // Ver: 00.00.01.10
+
+#endif // AMD_MEMORY_INFO_HOB_H_
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspBaseLibV2.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspBaseLibV2.h
new file mode 100644
index 0000000000..7547ecfe7b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspBaseLibV2.h
@@ -0,0 +1,248 @@
+/** @file
+     AMD Psp Base Lib
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AMD_PSP_BASELIB_V2_H_
+#define AMD_PSP_BASELIB_V2_H_
+
+#include <AMD.h>
+#include <AmdPspDirectory.h>
+
+#define PSP_MAILBOX_BASE           0x70                         ///< Mailbox base offset on PCIe BAR
+#define PSP_MAILBOX_STATUS_OFFSET  0x4                          ///< Staus Offset
+#define IS_ADDRESS_MODE_1(a)  (((a) >> 62) == 1 ? TRUE : FALSE) // relative to BIOS image base 0
+#define IS_ADDRESS_MODE_2(a)  (((a) >> 62) == 2 ? TRUE : FALSE) // relative to current directory header
+#define IS_ADDRESS_MODE_3(a)  (((a) >> 62) == 3 ? TRUE : FALSE) // relative to active image slot address (as of now, active image slot address is equal to PSP L2 base address)
+#define IS_SPI_OFFSET(a)      (((a) & 0xFF000000) != 0xFF000000 ? TRUE : FALSE)
+
+#define MaxDirEntryNumber     64
+#define MaxPspDirSize         sizeof(PSP_DIRECTORY_HEADER) + (sizeof(BIOS_DIRECTORY_ENTRY) * MaxDirEntryNumber)
+#define MAX_IMAGE_SLOT_COUNT  32
+
+#define ALIGNMENT_4K  BASE_4KB
+#define ALIGN_CHECK(addr, alignment)  ((((UINTN)(addr)) & ((alignment) - 1)) == 0)
+#define ALIGN_4K_CHECK(addr)          ALIGN_CHECK((addr), ALIGNMENT_4K)
+
+#define IS_VALID_ADDR32(addr)  (((UINT32)(addr) != 0) && (UINT32)(addr) != 0xFFFFFFFF)
+#define MaxImageSlotInfoSize  sizeof(IMAGE_SLOT_INFO)
+//
+// offset between Active Image Slot address and PSP L2 Directory
+//
+#define PSP_L2_DIR_OFFSET  0
+
+#pragma pack (push, 1)
+
+///
+/// X86 to PSP Buffer which start mapping from C2PMSG_28
+///
+typedef volatile struct {
+  UINT32    Status        : 16;             ///< Set by the target to indicate the execution status of last command
+  UINT32    CommandId     : 8;              ///< Command ID set by host
+  UINT32    Reserved      : 5;              ///< Reserved
+  UINT32    ResetRequired : 1;              // < Set by the target to indicate that the host has to execute warm reset if corrupted detected in tOS
+  UINT32    Recovery      : 1;              ///< Set by the target to indicate that the host has to execute FW recovery sequence
+  UINT32    Ready         : 1;              ///< Set by the target to indicate the mailbox interface state.
+} PSP_MBOX_V2_CMD_EXT;
+
+typedef volatile union {
+  IN  UINT32                 Value;               ///< Cmd register value
+  IN  PSP_MBOX_V2_CMD_EXT    Field;               ///< Extended Cmd register with field definition
+} PSP_MBOX_V2_CMD;
+
+typedef volatile struct {
+  PSP_MBOX_V2_CMD    Cmd;
+  UINT64             Buffer;               ///< 64 bit Ponter to memory with additional parameter.
+} PSP_MBOX_V2;
+
+#define FIRMWARE_TABLE_SIGNATURE  0x55AA55AAul
+/// Define the structure OEM signature table
+typedef struct _FIRMWARE_ENTRY_TABLEV2 {
+  UINT32    Signature;        ///< 0x00 Signature should be 0x55AA55AAul
+  UINT32    ImcRomBase;       ///< 0x04 Base Address for Imc Firmware
+  UINT32    GecRomBase;       ///< 0x08 Base Address for Gmc Firmware
+  UINT32    XHCRomBase;       ///< 0x0C Base Address for XHCI Firmware
+  UINT32    LegacyPspDirBase; ///< 0x10 Base Address of PSP directory for legacy program (ML, BP, CZ, BR, ST)
+  UINT32    PspDirBase;       ///< 0x14 Base Address for PSP directory
+  UINT32    ZpBiosDirBase;    ///< 0x18 Base Address for ZP BIOS directory
+  UINT32    RvBiosDirBase;    ///< 0x1C Base Address for RV BIOS directory
+  UINT32    SspBiosDirBase;   ///< 0x20 Base Address for RV BIOS directory
+  UINT32    Config;           ///< 0x24 reserved for EFS configuration
+  UINT32    NewBiosDirBase;   ///< 0x28 Generic Base address for all program start from RN
+  UINT32    PspDirBackupBase; ///< 0x2C Backup PSP directory address for all programs starting from RMB
+} FIRMWARE_ENTRY_TABLEV2;
+
+/// Unified Boot BIOS Directory structure
+enum _BIOS_DIRECTORY_ENTRY_TYPE {
+  BIOS_PUBLIC_KEY       = 0x05,               ///< PSP entry points to BIOS public key stored in SPI space
+  BIOS_RTM_SIGNATURE    = 0x07,               ///< PSP entry points to signed BIOS RTM hash stored  in SPI space
+  MAN_OS                = 0x5C,               ///< PSP entry points to manageability OS binary
+  MAN_IP_LIB            = 0x5D,               ///< PSP entry points to manageability proprietary IP library
+  MAN_CONFIG            = 0x5E,               ///< PSP entry points to manageability configuration inforamtion
+  BIOS_APCB_INFO        = 0x60,               ///< Agesa PSP Customization Block (APCB)
+  BIOS_APOB_INFO        = 0x61,               ///< Agesa PSP Output Block (APOB) target location
+  BIOS_FIRMWARE         = 0x62,               ///< BIOS Firmware volumes
+  APOB_NV_COPY          = 0x63,               ///< APOB data copy on non-volatile storage which will used by ABL during S3 resume
+  PMU_INSTRUCTION       = 0x64,               ///< Location field pointing to the instruction portion of PMU firmware
+  PMU_DATA              = 0x65,               ///< Location field pointing to the data portion of PMU firmware
+  UCODE_PATCH           = 0x66,               ///< Microcode patch
+  CORE_MCEDATA          = 0x67,               ///< Core MCE data
+  BIOS_APCB_INFO_BACKUP = 0x68,               ///< Backup Agesa PSP Customization Block (APCB)
+  BIOS_DIR_LV2          = 0x70,               ///< BIOS entry points to Level 2 BIOS DIR
+};
+
+/// Directory type
+typedef enum _DIRECTORY_TYPE {
+  DIR_TYPE_PSP_LV2  = 0,                      ///< Level 2 PSP DIR
+  DIR_TYPE_BIOS_LV2 = 1,                      ///< Level 2 BIOS DIR
+} DIRECTORY_TYPE;
+
+/// Type attribute for BIOS Directory entry
+typedef struct {
+  UINT32    Type           : 8; ///< [0:7], Type of BIOS entry
+  UINT32    RegionType     : 8; ///< [8:15], 0 Normal memory, 1 TA1 memory, 2 TA2 memor
+  UINT32    BiosResetImage : 1; ///< [16], Set for SEC or EL3 fw, which will be authenticate by PSP FW known as HVB
+  UINT32    Copy           : 1; ///< [17], Copy: 1- copy BIOS image image from source to destination 0- Set region attribute based on <ReadOnly, Source, size> attributes
+  UINT32    ReadOnly       : 1; ///< [18], 1: Set region to read-only (applicable for ARM- TA1/TA2) 0: Set region to read/write
+  UINT32    Compressed     : 1; ///< [19], 1: Compresed
+  UINT32    Instance       : 4; ///< [20:23], Specify the Instance of an entry
+  UINT32    SubProgram     : 3; ///< [24:26], < Specify the SubProgram
+  UINT32    RomId          : 2; ///< [27:28], Specify the RomId
+  UINT32    Reserved       : 3; ///< [29:31], Reserve for future use
+} TYPE_ATTRIB;
+
+/// Structure for PSP Entry
+typedef struct {
+  TYPE_ATTRIB    TypeAttrib;                    ///< Type of PSP entry; 32 bit long
+  UINT32         Size;                          ///< Size of PSP Entry in bytes
+  UINT64         Location;                      ///< Location of PSP Entry (byte offset from start of SPI-ROM)
+  UINT64         Destination;                   ///< Destination of PSP Entry copy to
+} BIOS_DIRECTORY_ENTRY;
+
+#define BIOS_DIRECTORY_HEADER_SIGNATURE      0x44484224ul ///< $BHD BIOS Directory Signature
+#define BIOS_LV2_DIRECTORY_HEADER_SIGNATURE  0x324C4224ul ///< $BL2 BIOS Directory Lv2 Signature
+/// Structure for BIOS directory
+typedef struct {
+  PSP_DIRECTORY_HEADER    Header;         ///< PSP directory header
+  BIOS_DIRECTORY_ENTRY    BiosEntry[1];   ///< Array of PSP entries each pointing to a binary in SPI flash
+                                          ///< The actual size of this array comes from the
+                                          ///< header (PSP_DIRECTORY.Header.TotalEntries)
+} BIOS_DIRECTORY;
+
+/// Structure for PSP Combo directory
+#define PSP_COMBO_DIRECTORY_COOKIE   0x50535032ul ///< 2PSP PSP Combo Directory Signature
+#define BIOS_COMBO_DIRECTORY_COOKIE  0x44484232ul ///< "BHD2" BIOS Combo Directory Signature
+
+typedef struct {
+  UINT32    Cookie;       ///< "2PSP" or "2BHD"
+  UINT32    Checksum;     ///< 32 bit CRC of header items below and the entire table
+  UINT32    TotalEntries; ///< Number of PSP Entries
+  UINT32    LookUpMode;   ///< 0 - Dynamic look up through all entries, 1 - PSP/chip ID match.
+  UINT8     Reserved[16]; ///< Reserved
+} COMBO_DIRECTORY_HEADER;
+
+/// Structure for PSP Combo directory entry
+typedef struct {
+  UINT32    IdSelect;     ///< 0 - Compare PSP ID, 1 - Compare chip family ID
+  UINT32    Id;           ///< 32-bit Chip/PSP ID
+  UINT64    DirTableAddr; ///< Point to PSP directory table (level 2)
+} COMBO_DIRECTORY_ENTRY;
+
+/**
+ * @brief PSP/BIOS entry region with start address and size
+ *
+ */
+typedef struct {
+  UINT64    Address;
+  UINT32    Size;
+} ENTRY_REGION;
+
+/// RECOVERY_REASON_VERSION
+typedef enum {
+  RECOVERY_REASON_VERSION_IGNORE = 0xFFFFFFFFul, // before RN
+  RECOVERY_REASON_VERSION_1      = 1,            // RN, CZN
+  RECOVERY_REASON_VERSION_2      = 2,            // Starting from VN
+} RECOVERY_REASON_VERSION;
+
+/// PSP Recovery Reason V1
+typedef struct {
+  UINT32    EntryType       : 16; ///< [0:15], Entry type ID of the binary in PSP/BIOS entry whose corruption caused recovery
+  UINT32    DirectoryLevel  : 2;  ///< [16:17],b'01--The entry is from PSP directory L1
+                                  ///          b'10--The entry is from PSP directory L2
+                                  ///          b'11--The entry is from BIOS directory L2
+  UINT32    Instance        : 4;  ///< [18:21],the instance number of the corrupted entry
+  UINT32    PartitionNumber : 3;  ///< [22:24],Which partition this log is from
+  UINT32    Reserved        : 7;  ///< [25:31] Reserve for future use
+} RECOVERY_REASON_V1;
+
+/// PSP Recovery Reason V2
+typedef struct {
+  UINT32    EntryType       : 8; ///< [0:7],  Entry type ID of the binary in PSP/BIOS entry whose corruption caused recovery
+  UINT32    Instance        : 4; ///< [8:11],the instance number of the corrupted entry
+  UINT32    SubProgram      : 4; ///< [12:15], SubProgram
+  UINT32    DirectoryLevel  : 4; ///< [16:19],b'01--The entry is from PSP directory L1
+                                 ///          b'10--The entry is from PSP directory L2
+                                 ///          b'11--The entry is from BIOS directory L2
+                                 ///          b'100--PSP L1 directory header
+                                 ///          b'101--PSP L2 directory header
+                                 ///          b'110--BIOS directory L2 header
+                                 ///          b'111--Image Slot Header
+  UINT32    Reserved        : 2; ///< [20:21], Reserved
+  UINT32    PartitionNumber : 3; ///< [22:24],Which partition this log is from
+  UINT32    Reserved2       : 7; ///< [25:31] Reserve for future use
+} RECOVERY_REASON_V2;
+
+#define VN_PSP_CHIP_ID  0xBC0B0800   ///< VN Chip ID in combo structure
+
+typedef struct {
+  COMBO_DIRECTORY_HEADER    Header;        ///< PSP Combo directory header
+  COMBO_DIRECTORY_ENTRY     ComboEntry[1]; ///<  Array of PSP combo entries each pointing to level 2 PSP Direcotry header
+} COMBO_DIRECTORY;
+
+#define IMAGE_SLOT_PRIORITY_UNBOOTABLE  0
+/// Structure for image slot entry, only used in family VN & MR
+//  It also used as structure to store ISH generic information accross programs
+typedef struct {
+  UINT32    Priority;
+  UINT32    UpdateRetries;
+  UINT32    GlitchRetries;
+  UINT32    ImageSlotAddr;
+} IMAGE_SLOT_HEADER;
+
+// Structure for image slot entry, start use from RMB
+// Major changes:
+// 1. Add CRC checksum
+// 2. Add PSPID to support combo, w/o combo directory
+// 3. Increased max entry number, 8 -> 32 (support up to 16 SOCs)
+// 4. Increased L1 as well as pointer in EFS (support multiple SOC image flash programming)
+typedef struct {
+  UINT32    CheckSum;      // [0x0000]
+  UINT32    Priority;      // [0x0004]
+  UINT32    UpdateRetries; // [0x0008]
+  UINT8     GlitchRetries; // [0x000C]
+  UINT8     Reserved[3];   // [0x000D]
+  UINT32    ImageSlotAddr; // [0x0010]
+  UINT32    PspId;         // [0x0014]
+  UINT32    SlotMaxSize;   // [0x0018]
+  UINT32    Reserved_1;    // [0x001C]
+} IMAGE_SLOT_HEADER_V2;          // [0x0020]
+
+typedef struct {
+  UINT32               SlotCount;                                 // the slot count in the system
+  UINT8                BootableSlotCount;                         // the bootable slot count in the system
+  UINT8                BootableSlotArray[MAX_IMAGE_SLOT_COUNT];   // bootable slot index array
+  UINT8                UnbootableSlotCount;                       // the unbootable slot count in the system
+  UINT8                UnbootableSlotArray[MAX_IMAGE_SLOT_COUNT]; // unbootable slot index array
+  UINT8                SlotAIndex;                                // index of slot with highest priority
+  IMAGE_SLOT_HEADER    SlotAHeader;                               // slot header with highest priority
+  UINT8                SlotBIndex;                                // index of slot with second highest priority
+  IMAGE_SLOT_HEADER    SlotBHeader;                               // slot header with second highest priority
+} IMAGE_SLOT_INFO;
+
+#pragma pack (pop)
+
+#define INSTANCE_IGNORED    0xFF
+#define SUBPROGRAM_IGNORED  0xFF
+#endif // AMD_LIB_H_
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspCommonLib.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspCommonLib.h
new file mode 100644
index 0000000000..78cc3ff559
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspCommonLib.h
@@ -0,0 +1,29 @@
+/** @file
+   AMD Psp Common Library header file
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AMD_PSPCOMMONLIB_H_
+#define AMD_PSPCOMMONLIB_H_
+
+#include <AmdPspDirectory.h>
+
+/*----------------------------------------------------------------------------------------
+ *                   D E F I N I T I O N S    A N D    M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+#define TCG_EVENT_BASE_AMD                   ((TCG_EVENTTYPE) 0x8000)
+#define TCG_EVENT_BASE_AMD_BIOS              (TCG_EVENT_BASE_AMD + 0x400)
+#define TCG_EVENT_AMD_BIOS_TSME_MEASUREMENT  (TCG_EVENT_BASE_AMD_BIOS + 1)
+
+BOOLEAN
+GetFtpmControlArea (
+  IN OUT   VOID  **FtpmControlArea
+  );
+
+#define PSPLIB_WAIT_INFINITELY  0xFFFFFFFFL
+
+#endif // AMD_PSPCOMMONLIB_H_
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspFtpmLib.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspFtpmLib.h
new file mode 100644
index 0000000000..0d320ab197
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Library/AmdPspFtpmLib.h
@@ -0,0 +1,94 @@
+/** @file
+   AMD Psp Ftpm Library header file
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PSP_FTPM_LIB_H_
+#define PSP_FTPM_LIB_H_
+#include <IndustryStandard/Acpi30.h>
+
+#define PSP_DEBUG_ENABLE  0
+
+#define HSP_VIDDID          0x163E1022
+#define HSP_TEMP_BAR0_SIZE  0x10000           // 64KB is enough
+
+//
+/// 1MB @todo check. Also move this to common header file and make it customizable
+/// perhaps fed it via build option etc
+#define FTPM_COMMAND_BUFFER_SIZE   (16*1024)
+#define FTPM_RESPONSE_BUFFER_SIZE  (16*1024)
+
+/* SYSTEM_TPM_CONFIG_VAL
+ *  Value range for APCB_TOKEN_UID_PSP_SYSTEM_TPM_CONFIG
+ */
+typedef enum {
+  SYSTEM_TPM_CONFIG_DTPM     = 0x00, ///< dTPM
+  SYSTEM_TPM_CONFIG_PSP_FTPM = 0x01, ///< PSP FTPM
+  SYSTEM_TPM_CONFIG_HSP_FTPM = 0x02, ///< HSP FTPM
+  SYSTEM_TPM_CONFIG_NONE     = 0xFF, ///< None of TPM
+} SYSTEM_TPM_CONFIG_VAL;
+
+#pragma pack (push, 1)
+/// Define TPM_2_CONTROL_AREA
+typedef struct {
+  // Interface Identifier
+  volatile UINT64         InterfaceIdentifier;        ///< Interface Identifier
+
+  // TPM2 Control Area Extension
+  volatile UINT32         Clear;                    ///< Clear
+  volatile UINT32         RemainingBytes;           ///< RemainingBytes
+  volatile UINT32         StatusReserved;           ///< StatusReserved
+  volatile UINT32         StatusError;              ///< StatusError
+  volatile UINT32         StatusCancel;             ///< StatusCancel
+  volatile UINT32         StatusStart;              ///< StatusStart
+  UINT64                  InterruptControl;         ///< InterruptControl
+  UINT32                  CommandSize;              ///< CommandSize
+  EFI_PHYSICAL_ADDRESS    CommandAddress;           ///< CommandAddress
+  UINT32                  ResponseSize;             ///< ResponseSize
+  EFI_PHYSICAL_ADDRESS    ResponseAddress;          ///< ResponseAddress
+  // Memory Absent command/response buffer
+  volatile UINT32         CmdRespHWBuffer;          ///< Cmd/Rsp HW Buffer
+} TPM2_CONTROL_AREA;
+
+#pragma pack (pop)
+
+/**
+  GET TPM related Info
+
+  @param[in,out] FtpmStatus              Used to hold more detail info (Unused Currently)
+
+  @return       EFI_SUCCESS              Ftpm function supported
+  @return       EFI_UNSUPPORTED          Ftpm function unsupported
+
+**/
+EFI_STATUS
+FtpmGetInfo (
+  IN OUT UINTN  *FtpmStatus
+  );
+
+/**
+   Execute a TPM command
+
+  @param[in]    CommandBuffer              Point to the TPM command buffer
+  @param[in]    CommandSize                Size of the TPM command buffer
+  @param[in]    ResponseBuffer             Point to the TPM response buffer
+  @param[in]    ResponseSize               Size of the TPM response buffer
+
+  @return       EFI_SUCCESS                Command executed successfully
+  @return       EFI_UNSUPPORTED            Device unsupported
+  @return       EFI_TIMEOUT                Command fail due the time out
+  @return       EFI_DEVICE_ERROR           Command fail due the error status set
+  @return       EFI_BUFFER_TOO_SMALL       Response buffer too small to hold the response
+
+**/
+EFI_STATUS
+FtpmExecuteCommand (
+  IN     VOID    *CommandBuffer,
+  IN     UINT32  CommandSize,
+  IN OUT VOID    *ResponseBuffer,
+  IN OUT UINT32  *ResponseSize
+  );
+
+#endif //PSP_FTPM_LIB_H_
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Ppi/AmdPspFtpmPpi.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Ppi/AmdPspFtpmPpi.h
new file mode 100644
index 0000000000..a41dd6cb71
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Ppi/AmdPspFtpmPpi.h
@@ -0,0 +1,80 @@
+/** @file
+     AMD Psp Ftpm Ppi Header
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PSP_FTPM_PPI_H_
+#define PSP_FTPM_PPI_H_
+#include <Uefi.h>
+typedef struct _PSP_FTPM_PPI PSP_FTPM_PPI;
+
+/// Define function prototype: Execute a TPM command
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_EXECUTE)(
+  IN     PSP_FTPM_PPI         *This,
+  IN     VOID                 *CommandBuffer,
+  IN     UINTN                CommandSize,
+  IN OUT VOID                 *ResponseBuffer,
+  IN OUT UINTN                *ResponseSize
+  );
+
+/// Define function prototype: GET TPM related Info
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_CHECK_STATUS)(
+  IN     PSP_FTPM_PPI         *This,
+  IN OUT UINTN                *FtpmStatus
+  );
+
+/// Define function prototype: Send a TPM command
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_SEND_COMMAND)(
+  IN     PSP_FTPM_PPI         *This,
+  IN     VOID                 *CommandBuffer,
+  IN     UINTN                 CommandSize
+  );
+
+/// Define function prototype: Get a TPM command's response
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_GET_RESPONSE)(
+  IN     PSP_FTPM_PPI          *This,
+  IN OUT VOID                  *ResponseBuffer,
+  IN OUT UINTN                 *ResponseSize
+  );
+
+/// Define function prototype: Get TCG Logs
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_GET_TCG_LOGS)(
+  IN     PSP_FTPM_PPI          *This,
+  IN OUT VOID                  *ResponseBuffer,
+  IN OUT UINTN                 *ResponseSize
+  );
+
+//
+// PPI prototype
+//
+// Defines PSP_FTPM_PPI. This PPI is used to get Ftpm info
+// Send TPM command, Get TPM command's response, Execute TPM command(Include send & get response)
+
+/// Define PSP_FTPM_PPI
+typedef struct _PSP_FTPM_PPI {
+  FTPM_EXECUTE         Execute;                           ///< Execute TPM command, include send & get response
+  FTPM_CHECK_STATUS    CheckStatus;                       ///< Check TPM Status
+  FTPM_SEND_COMMAND    SendCommand;                       ///< Send TPM command
+  FTPM_GET_RESPONSE    GetResponse;                       ///< Get Last TPM command response
+  FTPM_GET_TCG_LOGS    GetTcgLogs;                        ///< Get TCG Logs
+} PSP_FTPM_PPI;
+
+extern EFI_GUID  gAmdPspFtpmPpiGuid;
+extern EFI_GUID  gAmdPspFtpmFactoryResetPpiGuid;
+typedef struct _PSP_FTPM_FACTORY_RESET_PPI {
+  UINT8    Version;        ///< PPI Version
+} PSP_FTPM_FACTORY_RESET_PPI;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Protocol/AmdPspFtpmProtocol.h b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Protocol/AmdPspFtpmProtocol.h
new file mode 100644
index 0000000000..3449fcf6ad
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/AgesaPublic/Include/Protocol/AmdPspFtpmProtocol.h
@@ -0,0 +1,112 @@
+/** @file
+     AMD Psp Ftpm Protocol Header
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FTPM_PROTOCOL_H_
+#define FTPM_PROTOCOL_H_
+
+#include <Uefi.h>
+//
+// GUID definition
+//
+extern EFI_GUID  gAmdPspFtpmProtocolGuid;
+
+typedef struct {
+  // C2H_TPM_L0
+  UINT64    TPM_L0_Address;         // Mailbox address
+  UINT64    TPM_L0_C2H_MSG_Address; // Doorbell address CPU->HSP
+  UINT64    TPM_L0_H2C_MSG_Address; // Doorbell address HSP->CPU
+
+  // C2H_HSP_L0(VLT0)
+  UINT64    VLT0_Address;           // Mailbox address
+  UINT64    VLT0_C2H_MSG_Address;   // Doorbell address CPU->HSP
+  UINT64    VLT0_H2C_MSG_Address;   // Doorbell address HSP->CPU
+
+  // C2H_HSP_L1(VLT1)
+  UINT64    VLT1_Address;           // Mailbox address
+  UINT64    VLT1_C2H_MSG_Address;   // Doorbell address CPU->HSP
+  UINT64    VLT1_HSC_MSG_Address;   // Doorbell address HSP->CPU
+
+  // Interrupt Information
+  UINT8     Gsi[4];                 // Gsi[0] is for HSP Channel 0 TPM
+                                    // Gsi[1] is for HSP Channel 1 VTL0
+                                    // Gsi[2] is for HSP Channel 2 VTL1
+                                    // Gsi[3] is reserved
+} HSP_MAILBOX_ADDRESS, *PHSP_MAILBOX_ADDRESS;
+
+typedef union {
+  HSP_MAILBOX_ADDRESS    HSP_info;
+} FTPM_INFO;
+
+typedef struct _PSP_FTPM_PROTOCOL PSP_FTPM_PROTOCOL;
+
+/// Define function prototype: Execute a TPM command
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_EXECUTE)(
+  IN     PSP_FTPM_PROTOCOL    *This,
+  IN     VOID                 *CommandBuffer,
+  IN     UINT32                CommandSize,
+  IN OUT VOID                 *ResponseBuffer,
+  IN OUT UINT32               *ResponseSize
+  );
+
+/// Define function prototype: GET TPM related Info
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_CHECK_STATUS)(
+  IN     PSP_FTPM_PROTOCOL    *This,
+  IN OUT UINTN                *FtpmStatus
+  );
+
+/// Define function prototype: Send a TPM command
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_SEND_COMMAND)(
+  IN     PSP_FTPM_PROTOCOL    *This,
+  IN     VOID                 *CommandBuffer,
+  IN     UINT32                CommandSize
+  );
+
+/// Define function prototype: Get a TPM command's response
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_GET_RESPONSE)(
+  IN     PSP_FTPM_PROTOCOL     *This,
+  IN OUT VOID                  *ResponseBuffer,
+  IN OUT UINT32                *ResponseSize
+  );
+
+/// Define function prototype: Get TCG Logs
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_GET_TCG_LOGS)(
+  IN     PSP_FTPM_PROTOCOL     *This,
+  IN OUT VOID                  *ResponseBuffer,
+  IN OUT UINTN                 *ResponseSize
+  );
+
+/// Define function prototype: Get TPM info
+typedef
+EFI_STATUS
+(EFIAPI *FTPM_GET_TPM_INFO)(
+  IN     PSP_FTPM_PROTOCOL     *This,
+  IN OUT VOID                  *FtpmInfo
+  );
+
+/// Defines PSP_FTPM_PROTOCOL. This protocol is used to get Ftpm info
+/// Send TPM command, Get TPM command's response, Execute TPM command(Include send & get response)
+
+typedef struct _PSP_FTPM_PROTOCOL {
+  FTPM_EXECUTE         Execute;                           ///< Execute TPM command, include send & get response
+  FTPM_CHECK_STATUS    CheckStatus;                       ///< Check TPM Status
+  FTPM_SEND_COMMAND    SendCommand;                       ///< Send TPM command
+  FTPM_GET_RESPONSE    GetResponse;                       ///< Get Last TPM command response
+  FTPM_GET_TCG_LOGS    GetTcgLogs;                        ///< Get TCG Logs
+  FTPM_GET_TPM_INFO    GetInfo;                           ///< Get TPM info
+} PSP_FTPM_PROTOCOL;
+
+#endif //_FTPM_PROTOCOL_H_
--
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114579): https://edk2.groups.io/g/devel/message/114579
Mute This Topic: https://groups.io/mt/103975442/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 05/32] AMD/VanGoghBoard: Check in PlatformSecLib
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (3 preceding siblings ...)
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 04/32] AMD/VanGoghBoard: Check in AgesaPublicPkg Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:10 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 06/32] AMD/VanGoghBoard: Check in AmdIdsExtLib Zhai, MingXin (Duke) via groups.io
                   ` (27 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:10 UTC (permalink / raw)
  To: devel; +Cc: Duke Zhai, Eric Xing, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Chachani board jump to PlatformSec function after x86 releasing.
  This module provides the SEC entry function, which does platform-related
  early initialization.

Signed-off-by: Ken Yao <ken.yao@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Library/PlatformSecLib/Ia32/Flat32.nasm   | 534 ++++++++++++++++++
 .../Library/PlatformSecLib/Ia32/Platform.inc  |  53 ++
 .../Library/PlatformSecLib/PlatformSecLib.c   | 196 +++++++
 .../Library/PlatformSecLib/PlatformSecLib.inf |  61 ++
 .../PlatformSecLib/PlatformSecLibModStrs.uni  |  19 +
 5 files changed, 863 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Flat32.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Platform.inc
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLibModStrs.uni

diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Flat32.nasm b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Flat32.nasm
new file mode 100644
index 0000000000..5638c411e3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Flat32.nasm
@@ -0,0 +1,534 @@
+;/** @file
+; AMD VanGoghBoard PlatformSecLib
+;  This is the code that goes from real-mode to protected mode.
+;  It consumes the reset vector, configures the stack.
+;
+; Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;**/
+
+;
+; Include processor definitions
+;
+%use masm
+
+
+%include "Platform.inc"
+
+;
+; CR0 cache control bit definition
+;
+CR0_CACHE_DISABLE       EQU 040000000h
+CR0_NO_WRITE            EQU 020000000h
+BSP_STACK_BASE_ADDR     EQU FixedPcdGet32 (PcdPeiCorePeiPreMemoryStackBaseAddress)     ; Base address for core 0 stack
+PRE_MEM_STACK_SIZE      EQU FixedPcdGet32 (PcdPeiCorePeiPreMemoryStackSize)
+PCIEX_LENGTH_BIT_SETTING EQU 011000b
+
+MSR_IA32_EFER           EQU  0c0000080h       ; Extended Feature Enable Register
+MSR_IA32_EFER_LME       EQU  8                ; Long Mode Enable
+
+MSR_SMM_BASE            EQU  0c0010111h       ; SMBASE Register
+
+SMM_BASE_DEFAULT        EQU  30000h           ; reset value of MSR MSR_SMM_BASE
+
+SMMMASK_ADDRESS         EQU  0c0010113h       ; SMM TSeg Base Address
+SMMMASK_ADDRESS_AE      EQU  0                ; Aseg Address Range Enable
+SMMMASK_ADDRESS_TE      EQU  1                ; Tseg Address Range Enable
+
+;
+; In Modified Conventional Resume S3 Design:
+;   With Modified Conventional Resume path, the x86 resumes from sleep,
+; begins executing code from a predefined SMM resume vector and then
+; jump to ROM code to continue conventional resume.
+; EDX is filled with special signature "0x55AABB66" when jump to Sec,
+; this signature can be used to identify if resume back from SMM resume.
+;
+SMM_RESUME_SIGNATURE    EQU  055AABB66h
+
+PCAT_RTC_ADDRESS_REGISTER  EQU  0x70
+PCAT_RTC_DATA_REGISTER     EQU  0x71
+
+NMI_DISABLE_BIT         EQU  0x80
+
+RTC_ADDRESS_REGISTER_A  EQU  0x0A  ; R/W[0..6]  R0[7]
+RTC_ADDRESS_REGISTER_B  EQU  0x0B  ; R/W
+RTC_ADDRESS_REGISTER_C  EQU  0x0C  ; RO
+RTC_ADDRESS_REGISTER_D  EQU  0x0D  ; R/W
+
+;
+; External and public declarations
+;  TopOfStack is used by C code
+;  SecStartup is the entry point to the C code
+; Neither of these names can be modified without
+; updating the C code.
+;
+extern   ASM_PFX(SecStartup)
+
+SECTION .text
+;
+; Protected mode portion initializes stack, configures cache, and calls C entry point
+;
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    ProtectedModeEntryPoint
+;
+; Input:        Executing in 32 Bit Protected (flat) mode
+;                cs: 0-4GB
+;                ds: 0-4GB
+;                es: 0-4GB
+;                fs: 0-4GB
+;                gs: 0-4GB
+;                ss: 0-4GB
+;
+; Output:       This function never returns
+;
+; Destroys:
+;               ecx
+;               edi
+;                esi
+;                esp
+;
+; Description:
+;                Perform any essential early platform initilaisation
+;               Setup a stack
+;               Call the main EDKII Sec C code
+;
+;----------------------------------------------------------------------------
+
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+  ;
+  ; Check if system resumes from S3 SMM mode, if yes, continue to use S3 preserved stack setting
+  ;
+  cmp     edi, SMM_RESUME_SIGNATURE
+  je      S3_SecRoutine
+
+  JMP32   ASM_PFX(stackless_EarlyPlatformInit)
+  mov     esp, BSP_STACK_BASE_ADDR+PRE_MEM_STACK_SIZE
+
+  ;
+  ; Push processor count to stack first, then BIST status (AP then BSP)
+  ;
+  mov     eax, 1
+  cpuid
+  shr     ebx, 16
+  and     ebx, 0000000FFh
+  cmp     bl, 1
+  jae     PushProcessorCount
+
+  ;
+  ; Some processors report 0 logical processors.  Effectively 0 = 1.
+  ; So we fix up the processor count
+  ;
+  inc     ebx
+
+PushProcessorCount:
+  push    ebx
+
+  movd    eax, mm0  ; BIST saved in mm0 at reset vector.
+  ;
+  ; We need to implement a long-term solution for BIST capture.  For now, we just copy BSP BIST
+  ; for all processor threads
+  ;
+  mov     ecx, ebx
+PushBist:
+  push    eax
+  loop    PushBist
+
+  ;Clear Long Mode Enable
+  mov     ecx, MSR_IA32_EFER
+  rdmsr
+  btr     eax, MSR_IA32_EFER_LME          ; Set LME=0
+  wrmsr
+
+  ;Open smm ram
+  mov     ecx, SMMMASK_ADDRESS
+  rdmsr
+  btr     eax, SMMMASK_ADDRESS_AE          ; Set AValid=0
+  btr     eax, SMMMASK_ADDRESS_TE          ; Set TValid=0
+  wrmsr
+
+  ;Rebase SMRAM Base Address to power on default value
+  mov     ecx, MSR_SMM_BASE
+  rdmsr
+  mov     eax, SMM_BASE_DEFAULT
+  wrmsr
+
+  mov     ecx, APIC_BASE_ADDRESS
+  rdmsr
+  bt      eax, APIC_BSC                     ; Is this the BSC?
+  jc      IsBsp
+
+IsAp:
+  cli                                       ; Family 17h AP just halt here
+  hlt
+  jmp IsAp
+
+IsBsp:
+  push ebp  ; BFV base address
+  ;
+  ; Pass stack base into the PEI Core
+  ;
+  push    BSP_STACK_BASE_ADDR
+
+  ;
+  ; Pass stack size into the PEI Core
+  ;
+  push    PRE_MEM_STACK_SIZE
+  ;
+  ; Pass Control into the PEI Core
+  ;
+  ; UefiCpuPkg\SecCore\SecMain.c:
+  ;
+  ; VOID
+  ; EFIAPI
+  ; SecStartup (
+  ;   IN UINT32                   SizeOfRam,
+  ;   IN UINT32                   TempRamBase,
+  ;   IN VOID                     *BootFirmwareVolume
+  ;   );
+  call ASM_PFX(SecStartup)
+
+  ;
+  ; Sec Core should never return to here, this is just to capture an invalid return.
+  ;
+  jmp     $
+
+S3_SecRoutine:
+  ;Clear Long Mode Enable
+  mov     ecx, MSR_IA32_EFER
+  rdmsr
+  btr     eax, MSR_IA32_EFER_LME          ; Set LME=0
+  wrmsr
+
+  ;Open smm ram
+  mov     ecx, SMMMASK_ADDRESS
+  rdmsr
+  btr     eax, SMMMASK_ADDRESS_AE          ; Set AValid=0
+  btr     eax, SMMMASK_ADDRESS_TE          ; Set TValid=0
+  wrmsr
+
+  ;Rebase SMRAM Base Address to power on default value
+  mov     ecx, MSR_SMM_BASE
+  rdmsr
+  mov     eax, SMM_BASE_DEFAULT
+  wrmsr
+
+  mov     ecx, APIC_BASE_ADDRESS
+  rdmsr
+  bt      eax, APIC_BSC                     ; Is this the BSC?
+  jc      IsBspInS3
+
+IsApInS3:
+  cli                                       ; Family 17h AP just halt here
+  hlt
+  jmp     IsApInS3
+
+IsBspInS3:
+
+  ;;
+  ;; Enable eSPI port 80 and FCH UART2 during S3 resume start
+  ;;
+  push  eax
+  push  ebx
+  push  ecx
+  push  edx
+  push  esi
+  push  edi
+
+  mov     eax, FixedPcdGet64 (PcdPciExpressBaseAddress)
+  or      eax, (PCIEX_LENGTH_BIT_SETTING | 1)
+  xor     edx, edx
+  mov     ecx, 0C0010058h
+  wrmsr
+
+  ;
+  ; Enable port 80 decode to eSPI ;
+  ;
+  mov  ebx, FixedPcdGet64 (PcdPciExpressBaseAddress) | (LPC_PFA << 12) | LPC_SPI_BASE_ADDR  ; PCI Configuration address
+  mov  ebx, dword ptr [ebx]
+  and  ebx, 0xFFFFFF00
+  add  ebx, 0x10000 ; Get the eSPI base address
+  add  ebx, ESPI_SLAVE0_DECODE_EN
+  mov  eax, dword ptr [ebx]
+  or   eax, ESPI_SLAVE0_DECODE_EN_IO_80_EN
+  mov  dword ptr [ebx], eax
+
+  ;
+  ; Program IOMUX for eSPI port 80, GPIO 30 and 31 to function 1
+  ;
+  mov  ebx, 0xFED80D1E
+  mov  eax, dword ptr [ebx]
+  or   eax, 1
+  mov  dword ptr [ebx], eax
+
+  mov  ebx, 0xFED80D1F
+  mov  eax, dword ptr [ebx]
+  or   eax, 1
+  mov  dword ptr [ebx], eax
+
+  mov  al, 0x33
+  out  0x80, al
+
+  ;
+  ; Program IOMUX for FCH UART2, GPIO 136 and 138 to function 1
+  ;
+  mov  ebx, 0xFED80D88
+  mov  eax, dword ptr [ebx]
+  or   eax, 1
+  mov  dword ptr [ebx], eax
+
+  mov  ebx, 0xFED80D8A
+  mov  eax, dword ptr [ebx]
+  or   eax, 1
+  mov  dword ptr [ebx], eax
+
+  pop  edi
+  pop  esi
+  pop  edx
+  pop  ecx
+  pop  ebx
+  pop  eax
+  ;;
+  ;; Enable eSPI port 80 and FCH UART2 during S3 resume end
+  ;;
+
+  pop     ebx
+  mov     edi, ebx
+
+  pop     ebx
+  mov     esi, ebx
+
+  pop     edx
+  pop     eax
+
+  pop     ebx
+  mov     esp, ebx
+
+  push    1    ; set Processor Count to 1 for S3 resume path which is not used finally.
+  push    0    ; set BIST to 0
+
+  push    ebp  ; BFV base address
+
+  ;
+  ; Pass stack base into the PEI Core
+  ;
+  sub     ebx, PRE_MEM_STACK_SIZE
+  push    ebx
+
+  ;
+  ; Pass stack size into the PEI Core
+  ;
+  push    PRE_MEM_STACK_SIZE
+
+  ;
+  ; Pass Control into the PEI Core
+  ;
+  call    ASM_PFX(SecStartup)
+
+  ;
+  ; Sec Core should never return to here, this is just to capture an invalid return.
+  ;
+  jmp     $
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    stackless_EarlyPlatformInit
+;
+; Input:        esp - Return address
+;
+; Output:       None
+;
+; Destroys:
+;                eax
+;                ecx
+;                dx
+;                ebp
+;
+; Description:
+;        Any essential early platform initialisation required:
+;        (1) Setup PCIEXBAR access mechanism
+;        (2) enable IO port 80 to eSPI
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(stackless_EarlyPlatformInit)
+ASM_PFX(stackless_EarlyPlatformInit):
+
+  ;
+  ;PcRtcInit start
+  ;
+  ;;
+  ;; Initialize RTC Register
+  ;;
+  ;; Make sure Division Chain is properly configured,
+  ;; or RTC clock won't "tick" -- time won't increment
+  ;;
+  in      al,  PCAT_RTC_ADDRESS_REGISTER
+
+  mov     al,  RTC_ADDRESS_REGISTER_A | NMI_DISABLE_BIT
+  out     PCAT_RTC_ADDRESS_REGISTER,  al
+
+  mov     al,  FixedPcdGet8 (PcdInitialValueRtcRegisterA)
+  out     PCAT_RTC_DATA_REGISTER,  al
+
+
+  ;;
+  ;; Read Register B
+  ;;
+  in      al,  PCAT_RTC_ADDRESS_REGISTER
+
+  mov     al,  RTC_ADDRESS_REGISTER_B | NMI_DISABLE_BIT
+  out     PCAT_RTC_ADDRESS_REGISTER,  al
+
+  in      al,  PCAT_RTC_DATA_REGISTER
+
+
+  ;;
+  ;; Clear RTC flag register
+  ;;
+  in      al,  PCAT_RTC_ADDRESS_REGISTER
+
+  mov     al,  RTC_ADDRESS_REGISTER_C | NMI_DISABLE_BIT
+  out     PCAT_RTC_ADDRESS_REGISTER,  al
+
+  in      al,  PCAT_RTC_DATA_REGISTER
+
+
+  ;;
+  ;; Clear RTC register D
+  ;;
+  in      al,  PCAT_RTC_ADDRESS_REGISTER
+
+  mov     al,  RTC_ADDRESS_REGISTER_D | NMI_DISABLE_BIT
+  out     PCAT_RTC_ADDRESS_REGISTER,  al
+
+  mov     al,  FixedPcdGet8 (PcdInitialValueRtcRegisterD)
+  out     PCAT_RTC_DATA_REGISTER,  al
+  ;
+  ;PcRtcInit end
+  ;
+
+  mov     eax, FixedPcdGet64 (PcdPciExpressBaseAddress)
+  or      eax, (PCIEX_LENGTH_BIT_SETTING | 1)
+  xor     edx, edx
+  mov     ecx, 0C0010058h
+  wrmsr
+
+  ;
+  ; Enable port 80 decode to eSPI ;
+  ;
+  mov  ebx, FixedPcdGet64 (PcdPciExpressBaseAddress) | (LPC_PFA << 12) | LPC_SPI_BASE_ADDR  ; PCI Configuration address
+  mov  ebx, dword ptr [ebx]
+  and  ebx, 0xFFFFFF00
+  add  ebx, 0x10000 ; Get the eSPI base address
+  add  ebx, ESPI_SLAVE0_DECODE_EN
+  mov  eax, dword ptr [ebx]
+  or   eax, ESPI_SLAVE0_DECODE_EN_IO_80_EN
+  mov  dword ptr [ebx], eax
+
+  ;
+  ; Program IOMUX for eSPI port 80, GPIO 30 and 31 to function 1
+  ;
+  mov  ebx, 0xFED80D1E
+  mov  eax, dword ptr [ebx]
+  or   eax, 1
+  mov  dword ptr [ebx], eax
+
+  mov  ebx, 0xFED80D1F
+  mov  eax, dword ptr [ebx]
+  or   eax, 1
+  mov  dword ptr [ebx], eax
+
+  mov  al, 0x88
+  out  0x80, al
+
+
+  ;
+  ; Program IOMUX for FCH UART2, GPIO 136 and 138 to function 1
+  ;
+  mov  ebx, 0xFED80D88
+  mov  eax, dword ptr [ebx]
+  or   eax, 1
+  mov  dword ptr [ebx], eax
+
+  mov  ebx, 0xFED80D8A
+  mov  eax, dword ptr [ebx]
+  or   eax, 1
+  mov  dword ptr [ebx], eax
+
+  RET32
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    stackless_PCIConfig_Write
+;
+; Input:        esp - return address
+;                eax - Data to write
+;                ebx - PCI Config Address
+;
+; Output:       None
+;
+; Destroys:
+;                dx
+;
+; Description:
+;        Perform a DWORD PCI Configuration write
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(stackless_PCIConfig_Write)
+ASM_PFX(stackless_PCIConfig_Write):
+
+  ;
+  ; Write the PCI Config Address to the address port
+  ;
+  xchg  eax, ebx
+  mov  dx, PCI_ADDRESS_PORT
+  out  dx, eax
+  xchg  eax, ebx
+
+  ;
+  ; Write the PCI DWORD Data to the data port
+  ;
+  mov  dx, PCI_DATA_PORT
+  out  dx, eax
+
+  RET32
+
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    stackless_PCIConfig_Read
+;
+; Input:        esp - return address
+;                ebx - PCI Config Address
+;
+; Output:       eax - Data read
+;
+; Destroys:
+;                eax
+;                dx
+;
+; Description:
+;        Perform a DWORD PCI Configuration read
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(stackless_PCIConfig_Read)
+ASM_PFX(stackless_PCIConfig_Read):
+  ;
+  ; Write the PCI Config Address to the address port
+  ;
+  xchg  eax, ebx
+  mov  dx, PCI_ADDRESS_PORT
+  out  dx, eax
+  xchg  eax, ebx
+
+  ;
+  ; Read the PCI DWORD Data from the data port
+  ;
+  mov  dx, PCI_DATA_PORT
+  in  eax, dx
+
+  RET32
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Platform.inc b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Platform.inc
new file mode 100644
index 0000000000..7ef0d9a2c0
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/Ia32/Platform.inc
@@ -0,0 +1,53 @@
+;/** @file
+; AMD VanGoghBoard PlatformSecLib
+; Platform Specific Definitions
+;
+; Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;**/
+
+%macro JMP32 1
+  lea  esp, %%target
+  jmp  %1
+%%target:
+%endmacro
+
+%macro RET32 0
+    jmp    esp
+%endmacro
+
+;
+; RTC/CMOS definitions
+;
+RTC_INDEX      EQU 070h
+  NMI_DISABLE  EQU 080h    ; Bit7=1 disables NMI
+  NMI_ENABLE  EQU 000h    ; Bit7=0 disables NMI
+RTC_DATA      EQU 071h
+
+;
+; PCI Configuration definitions
+;
+PCI_CFG            EQU 1 << 01Fh  ; PCI configuration access mechanism
+PCI_ADDRESS_PORT   EQU 0CF8h
+PCI_DATA_PORT      EQU 0CFCh
+
+;
+; LPC-ISA Bridge PCI Config Registers
+;
+LPC_PFA            EQU 00A3h          ; B0:D14:F3 (Legacy Block)
+  LPC_IO_PDE         EQU 0044h        ; IO Port Decode Enable
+  LPC_IOMEM_PDE      EQU 0048h        ; IO or Memory Port Decode Enable
+  LPC_BASE_WIDE_PORT EQU 0064H
+  LPC_WIDE_IO_EN     EQU 0074H
+  LPC_WIDE_IO2       EQU 0090H
+  LPC_SPI_BASE_ADDR  EQU 00A0H        ; SPI BAR = {SPI_BaseAddr[31:8],8'b0}
+                                      ; HFP BAR = {SPI_BaseAddr[31:8],8'b0} + 0x0000_1000
+                                      ; eSPI BAR = {SPI_BaseAddr[31:8],8'b0} + 0x0001_0000
+
+ESPI_SLAVE0_DECODE_EN EQU 0040h
+  ESPI_SLAVE0_DECODE_EN_IO_80_EN EQU  04h  ; Port 80 decode enabled
+
+APIC_BASE_ADDRESS       EQU 0000001Bh
+APIC_BSC                EQU 8       ; Boot Strap Core
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.c b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.c
new file mode 100644
index 0000000000..c5f7cc6018
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.c
@@ -0,0 +1,196 @@
+/** @file
+Platform SEC Library for Quark.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/TemporaryRamSupport.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/MtrrLib.h>
+
+/**
+
+  Entry point to the C language phase of SEC. After the SEC assembly
+  code has initialized some temporary memory and set up the stack,
+  the control is transferred to this function.
+
+  @param SizeOfRam           Size of the temporary memory available for use.
+  @param TempRamBase         Base address of temporary ram
+  @param BootFirmwareVolume  Base address of the Boot Firmware Volume.
+
+**/
+VOID
+EFIAPI
+SecStartup (
+  IN UINT32  SizeOfRam,
+  IN UINT32  TempRamBase,
+  IN VOID    *BootFirmwareVolume
+  );
+
+/**
+  Auto-generated function that calls the library constructors for all of the module's
+  dependent libraries.  This function must be called by the SEC Core once a stack has
+  been established.
+
+**/
+VOID
+EFIAPI
+ProcessLibraryConstructorList (
+  VOID
+  );
+
+/**
+
+  Entry point to the C language phase of PlatformSecLib.  After the SEC assembly
+  code has initialized some temporary memory and set up the stack, control is
+  transferred to this function.
+
+**/
+VOID
+EFIAPI
+PlatformSecLibStartup (
+  VOID
+  )
+{
+  //
+  // Process all library constructor functions linked to SecCore.
+  // This function must be called before any library functions are called
+  //
+  ProcessLibraryConstructorList ();
+
+  //
+  // Set write back cache attribute for SPI FLASH
+  //
+
+  //
+  // Set write back cache attribute for 512KB Embedded SRAM
+  //
+
+  //
+  // Pass control to SecCore module passing in the size of the temporary RAM in
+  // Embedded SRAM, the base address of the temporary RAM in Embedded SRAM, and
+  // the base address of the boot firmware volume.  The top 32KB of the 512 KB
+  // embedded SRAM are used as temporary RAM.
+  //
+  SecStartup (
+    SIZE_128KB,
+    BASE_64KB + BASE_128KB,
+    (VOID *)(UINTN)(PcdGet32 (PcdMemoryFvRecoveryBase))
+    );
+}
+
+/**
+  A developer supplied function to perform platform specific operations.
+
+  It's a developer supplied function to perform any operations appropriate to a
+  given platform. It's invoked just before passing control to PEI core by SEC
+  core. Platform developer may modify the SecCoreData and PPI list that is
+  passed to PEI Core.
+
+  @param  SecCoreData           The same parameter as passing to PEI core. It
+                                could be overridden by this function.
+  @param  PpiList               The default PPI list passed from generic SEC
+                                part.
+
+  @return The final PPI list that platform wishes to passed to PEI core.
+
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+EFIAPI
+SecPlatformMain (
+  IN OUT   EFI_SEC_PEI_HAND_OFF  *SecCoreData
+  )
+{
+  MtrrSetMemoryAttribute (PcdGet32 (PcdMemoryFvRecoveryBase), PcdGet32 (PcdMemoryFvMainSize) + PcdGet32 (PcdFlashFvRecoverySize), CacheWriteBack);
+  return NULL;
+}
+
+/**
+  This interface conveys state information out of the Security (SEC) phase into PEI.
+
+  @param  PeiServices               Pointer to the PEI Services Table.
+  @param  StructureSize             Pointer to the variable describing size of the input buffer.
+  @param  PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+  @retval EFI_SUCCESS           The data was successfully returned.
+  @retval EFI_BUFFER_TOO_SMALL  The buffer was too small.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformation (
+  IN CONST EFI_PEI_SERVICES                  **PeiServices,
+  IN OUT   UINT64                            *StructureSize,
+  OUT   EFI_SEC_PLATFORM_INFORMATION_RECORD  *PlatformInformationRecord
+  )
+{
+  UINT32             *BIST;
+  UINT32             Size;
+  UINT32             Count;
+  EFI_HOB_GUID_TYPE  *GuidHob;
+  UINT32             *TopOfStack;
+
+  //
+  // Top of the stack is the top of the 512KB Embedded SRAM region
+  //
+  TopOfStack = (UINT32 *)(FixedPcdGet32 (PcdPeiCorePeiPreMemoryStackBaseAddress) +
+                          FixedPcdGet32 (PcdPeiCorePeiPreMemoryStackSize));
+
+  GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformationPpiGuid);
+  if (GuidHob != NULL) {
+    Size = GET_GUID_HOB_DATA_SIZE (GuidHob);
+    BIST = GET_GUID_HOB_DATA (GuidHob);
+  } else {
+    //
+    // The entries of BIST information, together with the number of them,
+    // reside in the bottom of stack, left untouched by normal stack operation.
+    // This routine copies the BIST information to the buffer pointed by
+    // PlatformInformationRecord for output.
+    //
+    Count = *(TopOfStack - 1);
+    Size  = Count * sizeof (IA32_HANDOFF_STATUS);
+    BIST  = (UINT32 *)((UINT32)TopOfStack - sizeof (UINT32) - Size);
+
+    //
+    // Copy Data from Stack to Hob to avoid data is lost after memory is ready.
+    //
+    BuildGuidDataHob (
+      &gEfiSecPlatformInformationPpiGuid,
+      BIST,
+      (UINTN)Size
+      );
+    GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformationPpiGuid);
+    Size    = GET_GUID_HOB_DATA_SIZE (GuidHob);
+    BIST    = GET_GUID_HOB_DATA (GuidHob);
+  }
+
+  if ((*StructureSize) < (UINT64)Size) {
+    *StructureSize = Size;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *StructureSize = Size;
+  CopyMem (PlatformInformationRecord, BIST, Size);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This interface disables temporary memory in SEC Phase.
+**/
+VOID
+EFIAPI
+SecPlatformDisableTemporaryMemory (
+  VOID
+  )
+{
+}
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.inf b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.inf
new file mode 100644
index 0000000000..baa7939e46
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLib.inf
@@ -0,0 +1,61 @@
+#/** @file
+# Platform SEC Library for Quark.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformSecLib
+  FILE_GUID                      = E9536686-F280-4908-88DA-DBBCD0186A6A
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformSecLib
+  MODULE_UNI_FILE                = PlatformSecLibModStrs.uni
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  PlatformSecLib.c
+
+[Sources.IA32]
+  Ia32/Flat32.nasm
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PcAtChipsetPkg/PcAtChipsetPkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  DebugLib
+  BaseLib
+  BaseMemoryLib
+  PciLib
+  PcdLib
+  HobLib
+  MtrrLib
+
+[Pcd]
+  gPlatformPkgTokenSpaceGuid.PcdFlashFvRecoverySize     ## CONSUMES
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gPlatformPkgTokenSpaceGuid.PcdMemoryFvRecoveryBase
+  gAmdCommonPkgTokenSpaceGuid.PcdMemoryFvMainSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate
+  gPlatformPkgTokenSpaceGuid.PcdPeiCorePeiPreMemoryStackBaseAddress
+  gPlatformPkgTokenSpaceGuid.PcdPeiCorePeiPreMemoryStackSize
+  gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterA     ## CONSUMES
+  gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterD     ## CONSUMES
+
+[Ppis]
+  gEfiSecPlatformInformationPpiGuid   ## UNDEFINED # it is used as GUIDED HOB
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLibModStrs.uni b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLibModStrs.uni
new file mode 100644
index 0000000000..93ee4a65dc
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/PlatformSecLib/PlatformSecLibModStrs.uni
@@ -0,0 +1,19 @@
+// /** @file
+// PlatformSecLib Localized Abstract and Description Content
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT
+#language en-US
+"SEC Platform Library "
+
+#string STR_MODULE_DESCRIPTION
+#language en-US
+"Provides a platform-specific function to be used during the SEC stage of POST. "
+
+
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114583): https://edk2.groups.io/g/devel/message/114583
Mute This Topic: https://groups.io/mt/103975446/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 06/32] AMD/VanGoghBoard: Check in AmdIdsExtLib
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (4 preceding siblings ...)
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 05/32] AMD/VanGoghBoard: Check in PlatformSecLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:10 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 07/32] AMD/VanGoghBoard: Check in PciPlatform Zhai, MingXin (Duke) via groups.io
                   ` (26 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:10 UTC (permalink / raw)
  To: devel; +Cc: Duke Zhai, Eric Xing, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  A small part of Chachani platform code and FSPWrapperPkg needs IdsHookExtLib.
  Initial AmdIdsHookExtLibNull for ChachaniBoardPkg module.

Signed-off-by: Ken Yao <ken.yao@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../AmdIdsExtLibNull/AmdIdsHookExtLibNull.c   | 33 ++++++++++++++++
 .../AmdIdsExtLibNull/AmdIdsHookExtLibNull.inf | 39 +++++++++++++++++++
 2 files changed, 72 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.inf

diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.c b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.c
new file mode 100644
index 0000000000..f59b5beea1
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.c
@@ -0,0 +1,33 @@
+/** @file
+  Implements AmdIdsHookExtLibNull.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+
+typedef enum {
+  IDS_HOOK_UNSUPPORTED = 1
+} IDS_HOOK_STATUS;
+
+IDS_HOOK_STATUS
+IdsHookExtEntry (
+  UINT32  HookId,
+  VOID    *Handle,
+  VOID    *Data
+  )
+{
+  return IDS_HOOK_UNSUPPORTED;
+}
+
+IDS_HOOK_STATUS
+GetIdsNvTable (
+  IN OUT   VOID    *IdsNvTable,
+  IN OUT   UINT32  *IdsNvTableSize
+  )
+{
+  return IDS_HOOK_UNSUPPORTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.inf b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.inf
new file mode 100644
index 0000000000..354c19dd19
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Library/AmdIdsExtLibNull/AmdIdsHookExtLibNull.inf
@@ -0,0 +1,39 @@
+## @file
+#  Amd Ids Hook Ext Lib Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = AmdIdsHookExtLibNull.inf
+  FILE_GUID                      = CB364A1C-793D-46CE-B80A-0AB5FCB16D76
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = AmdIdsHookExtLib
+
+[Sources.common]
+  AmdIdsHookExtLibNull.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+
+[Guids]
+
+[Protocols]
+
+[Ppis]
+
+[FeaturePcd]
+
+[Pcd]
+
+[Depex]
+  TRUE
+
+[BuildOptions]
+
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114580): https://edk2.groups.io/g/devel/message/114580
Mute This Topic: https://groups.io/mt/103975443/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 07/32] AMD/VanGoghBoard: Check in PciPlatform
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (5 preceding siblings ...)
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 06/32] AMD/VanGoghBoard: Check in AmdIdsExtLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 08/32] AMD/VanGoghBoard: Check in UDKFlashUpdate Zhai, MingXin (Duke) via groups.io
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  BIOS detects current IGPU device ID and install corresponding VBIOS.
  Inital PciPlatform module to load VBIOS and to provide interface for
  other option ROMs if necessary.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Include/Protocol/GlobalNvsArea.h          |  63 ++++++
 .../PciPlatform/CommonHeader.h                |  27 +++
 .../PciPlatform/PciPlatform.c                 | 183 ++++++++++++++++++
 .../PciPlatform/PciPlatform.h                 |  89 +++++++++
 .../PciPlatform/PciPlatform.inf               |  51 +++++
 5 files changed, 413 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Protocol/GlobalNvsArea.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/CommonHeader.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.c
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.h
 create mode 100644 Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.inf

diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Protocol/GlobalNvsArea.h b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Protocol/GlobalNvsArea.h
new file mode 100644
index 0000000000..36d4f43ebd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/Include/Protocol/GlobalNvsArea.h
@@ -0,0 +1,63 @@
+/** @file
+Definition of the global NVS area protocol.  This protocol
+publishes the address and format of a global ACPI NVS buffer
+used as a communications buffer between SMM code and ASL code.
+The format is derived from the ACPI reference code, version 0.95.
+Note:  Data structures defined in this protocol are not naturally aligned.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef GLOBAL_NVS_AREA_H_
+#define GLOBAL_NVS_AREA_H_
+
+//
+// Includes
+//
+#define GLOBAL_NVS_DEVICE_ENABLE   1
+#define GLOBAL_NVS_DEVICE_DISABLE  0
+
+//
+// Global NVS Area Protocol GUID
+//
+#define EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID \
+{ 0x74e1e48, 0x8132, 0x47a1, {0x8c, 0x2c, 0x3f, 0x14, 0xad, 0x9a, 0x66, 0xdc} }
+
+//
+// Revision id - Added TPM related fields
+//
+#define GLOBAL_NVS_AREA_RIVISION_1  1
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID  gEfiGlobalNvsAreaProtocolGuid;
+
+//
+// Global NVS Area definition
+//
+#pragma pack (1)
+typedef struct {
+  //
+  // Miscellaneous Dynamic Values, the definitions below need to be matched
+  // GNVS definitions in Platform.ASL
+  //
+  UINT32    TopOfMem;               // TOPM
+  UINT8     NbIoApic;               // NAPC
+  UINT32    PcieBaseAddress;        // PCBA
+  UINT32    PcieBaseLimit;          // PCBL
+} EFI_GLOBAL_NVS_AREA;
+#pragma pack ()
+
+//
+// Global NVS Area Protocol
+//
+typedef struct _EFI_GLOBAL_NVS_AREA_PROTOCOL {
+  EFI_GLOBAL_NVS_AREA    *Area;
+} EFI_GLOBAL_NVS_AREA_PROTOCOL;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/CommonHeader.h b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/CommonHeader.h
new file mode 100644
index 0000000000..1297de6369
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/CommonHeader.h
@@ -0,0 +1,27 @@
+/** @file
+  Implements CommonHeader.h
+  This file includes package header files, library classes and protocol, PPI & GUID definitions.
+
+  Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef COMMON_HEADER_H_
+#define COMMON_HEADER_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/PciPlatform.h>
+#include <Protocol/PciIo.h>
+
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.c b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.c
new file mode 100644
index 0000000000..aa0a133b1f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.c
@@ -0,0 +1,183 @@
+/** @file
+  Implements PciPlatform.c
+  Registers onboard PCI ROMs with PCI.IO
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CommonHeader.h"
+
+#include "PciPlatform.h"
+
+PCI_OPTION_ROM_TABLE  mPciOptionRomTable[] = {
+  { ONBOARD_SPH_VIDEO_OPTION_ROM_FILE_GUID, 0x1002, 0x1435 },
+  { NULL_ROM_FILE_GUID,                     0xffff, 0xffff }
+};
+
+EFI_PCI_PLATFORM_PROTOCOL  mPciPlatform = {
+  PhaseNotify,
+  PlatformPrepController,
+  GetPlatformPolicy,
+  GetPciRom
+};
+
+EFI_HANDLE  mPciPlatformHandle = NULL;
+EFI_HANDLE  mImageHandle       = NULL;
+
+EFI_STATUS
+EFIAPI
+PhaseNotify (
+  IN EFI_PCI_PLATFORM_PROTOCOL                      *This,
+  IN EFI_HANDLE                                     HostBridge,
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN EFI_PCI_CHIPSET_EXECUTION_PHASE                ChipsetPhase
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+PlatformPrepController (
+  IN  EFI_PCI_PLATFORM_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                    HostBridge,
+  IN  EFI_HANDLE                                    RootBridge,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS   PciAddress,
+  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN  EFI_PCI_CHIPSET_EXECUTION_PHASE               ChipsetPhase
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Get PlatformPolicy for VGA IO ALIAS
+
+  @param This       Protocol instance pointer.
+  @param PciPolicy  PCI Platform Policy.
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformPolicy (
+  IN  CONST EFI_PCI_PLATFORM_PROTOCOL  *This,
+  OUT       EFI_PCI_PLATFORM_POLICY    *PciPolicy
+  )
+{
+  *PciPolicy |= EFI_RESERVE_VGA_IO_ALIAS;
+  return EFI_SUCCESS;
+}
+
+/**
+  Return a PCI ROM image for the onboard device represented by PciHandle
+
+  @param This       Protocol instance pointer.
+  @param PciHandle  PCI device to return the ROM image for.
+  @param RomImage   PCI Rom Image for onboard device
+  @param RomSize    Size of RomImage in bytes
+
+  @retval EFI_SUCCESS   - RomImage is valid
+  @retval EFI_NOT_FOUND - No RomImage
+
+**/
+EFI_STATUS
+EFIAPI
+GetPciRom (
+  IN  CONST EFI_PCI_PLATFORM_PROTOCOL  *This,
+  IN        EFI_HANDLE                 PciHandle,
+  OUT       VOID                       **RomImage,
+  OUT       UINTN                      *RomSize
+  )
+{
+  EFI_STATUS           Status;
+  EFI_PCI_IO_PROTOCOL  *PciIo;
+  UINTN                Segment;
+  UINTN                Bus;
+  UINTN                Device;
+  UINTN                Function;
+  UINT16               VendorId;
+  UINT16               DeviceId;
+  UINTN                TableIndex;
+
+  Status = gBS->HandleProtocol (
+                  PciHandle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **)&PciIo
+                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0, 1, &VendorId);
+
+  PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 2, 1, &DeviceId);
+
+  //
+  // Loop through table of video option rom descriptions
+  //
+  for (TableIndex = 0; mPciOptionRomTable[TableIndex].VendorId != 0xffff; TableIndex++) {
+    //
+    // See if the PCI device specified by PciHandle matches at device in mPciOptionRomTable
+    //
+    if ((VendorId != mPciOptionRomTable[TableIndex].VendorId) ||
+        (DeviceId != mPciOptionRomTable[TableIndex].DeviceId))
+    {
+      continue;
+    }
+
+    Status = GetSectionFromAnyFv (
+               &mPciOptionRomTable[TableIndex].FileName,
+               EFI_SECTION_RAW,
+               0,
+               RomImage,
+               RomSize
+               );
+
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+
+  @param  ImageHandle  Handle of driver image.
+  @param  SystemTable  Pointer to system table.
+
+  @retval EFI_STATUS return status of InstallProtocolInterface.
+
+**/
+EFI_STATUS
+EFIAPI
+PciPlatformDriverEntry (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  mImageHandle = ImageHandle;
+
+  //
+  // Install on a new handle
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mPciPlatformHandle,
+                  &gEfiPciPlatformProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mPciPlatform
+                  );
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.h b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.h
new file mode 100644
index 0000000000..a0a4e01161
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.h
@@ -0,0 +1,89 @@
+/** @file
+  Implements PciPlatform.h
+  This code supports a the private implementation
+  of the Legacy BIOS Platform protocol
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PCI_PLATFORM_H_
+#define PCI_PLATFORM_H_
+
+#include <IndustryStandard/Pci.h>
+#include <Library/PcdLib.h>
+//
+// Global variables for Option ROMs
+//
+#define NULL_ROM_FILE_GUID \
+{ 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}
+
+#define ONBOARD_SPH_VIDEO_OPTION_ROM_FILE_GUID \
+{ 0xE7D31EB4, 0x90F3, 0x4A14, {0x8A, 0x28, 0x48, 0xD0, 0x47, 0x42, 0xF8, 0xE1 }}
+
+typedef struct {
+  EFI_GUID    FileName;
+  UINT16      VendorId;
+  UINT16      DeviceId;
+} PCI_OPTION_ROM_TABLE;
+
+EFI_STATUS
+EFIAPI
+PhaseNotify (
+  IN EFI_PCI_PLATFORM_PROTOCOL                      *This,
+  IN EFI_HANDLE                                     HostBridge,
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN EFI_PCI_CHIPSET_EXECUTION_PHASE                ChipsetPhase
+  );
+
+EFI_STATUS
+EFIAPI
+PlatformPrepController (
+  IN  EFI_PCI_PLATFORM_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                    HostBridge,
+  IN  EFI_HANDLE                                    RootBridge,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS   PciAddress,
+  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN  EFI_PCI_CHIPSET_EXECUTION_PHASE               ChipsetPhase
+  );
+
+/**
+  Get PlatformPolicy for VGA IO ALIAS
+
+  @param This       Protocol instance pointer.
+  @param PciPolicy  PCI Platform Policy.
+
+  @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformPolicy (
+  IN  CONST EFI_PCI_PLATFORM_PROTOCOL  *This,
+  OUT       EFI_PCI_PLATFORM_POLICY    *PciPolicy
+  );
+
+/**
+  Return a PCI ROM image for the onboard device represented by PciHandle
+
+  @param This       Protocol instance pointer.
+  @param PciHandle  PCI device to return the ROM image for.
+  @param RomImage   PCI Rom Image for onboard device
+  @param RomSize    Size of RomImage in bytes
+
+  @retval EFI_SUCCESS   - RomImage is valid
+  @retval EFI_NOT_FOUND - No RomImage
+
+**/
+EFI_STATUS
+EFIAPI
+GetPciRom (
+  IN CONST EFI_PCI_PLATFORM_PROTOCOL  *This,
+  IN       EFI_HANDLE                 PciHandle,
+  OUT      VOID                       **RomImage,
+  OUT      UINTN                      *RomSize
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.inf b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.inf
new file mode 100644
index 0000000000..16028400ce
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/PciPlatform.inf
@@ -0,0 +1,51 @@
+## @file
+#  PCI Platform  INF file
+# This driver installs pciplatform protocol to provide access interfaces to the onboard pci roms.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PciPlatform
+  FILE_GUID                      = E78AE2BF-D5E8-4846-9B0A-2D54AEC3BAF9
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PciPlatformDriverEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  PciPlatform.c
+  PciPlatform.h
+  CommonHeader.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  PciLib
+  PcdLib
+  DebugLib
+  UefiRuntimeServicesTableLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  DxeServicesLib
+
+[Guids]
+
+[Protocols]
+  gEfiPciIoProtocolGuid                         # PROTOCOL ALWAYS_CONSUMED
+  gEfiPciPlatformProtocolGuid                   # PROTOCOL ALWAYS_PRODUCED
+
+[Pcd]
+
+[Depex]
+  TRUE
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114582): https://edk2.groups.io/g/devel/message/114582
Mute This Topic: https://groups.io/mt/103975445/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 08/32] AMD/VanGoghBoard: Check in UDKFlashUpdate
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (6 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 07/32] AMD/VanGoghBoard: Check in PciPlatform Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 09/32] AMD/VanGoghBoard: Check in Flash_AB Zhai, MingXin (Duke) via groups.io
                   ` (24 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  UDKFlashUpdate is a uefi tool for BIOS binary updating. It depends on EDK2's flash access protocol.
  UDKFlashUpdate needs to run under EDK2 BIOS.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../UDKFlashUpdate/SpiFlashDevice.c           |  37 +
 .../UDKFlashUpdate/SpiFlashDevice.h           |  62 ++
 .../UDKFlashUpdate/UDKFlashUpdate.c           | 671 ++++++++++++++++++
 .../UDKFlashUpdate/UDKFlashUpdate.h           |  48 ++
 .../UDKFlashUpdate/UDKFlashUpdate.inf         |  51 ++
 5 files changed, 869 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.inf

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.c
new file mode 100644
index 0000000000..d4f5b12f41
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.c
@@ -0,0 +1,37 @@
+/** @file
+  Implements SpiFlashDevice.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SpiFlashDevice.h"
+
+SPI_INIT_TABLE  mSpiInitTable[] = {
+  { // W25Q256JW/W74M25JW
+    SF_VENDOR_ID_WINBOND,
+    SF_DEVICE_ID0_W25Q256JW,
+    SF_DEVICE_ID1_W25Q256JW,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_JEDEC_ID,          EnumSpiOperationJedecId            },
+      { EnumSpiOpcodeWriteNoAddr,SPI_COMMAND_WRITE_S,           EnumSpiOperationWriteStatus        },
+      { EnumSpiOpcodeWrite,    SPI_COMMAND_WRITE,             EnumSpiOperationProgramData_1_Byte },
+      { EnumSpiOpcodeRead,     SPI_COMMAND_READ,              EnumSpiOperationReadData           },
+      { EnumSpiOpcodeWrite,    SPI_COMMAND_ERASE,             EnumSpiOperationErase_4K_Byte      },
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_READ_S,            EnumSpiOperationReadStatus         },
+      { EnumSpiOpcodeWriteNoAddr,SPI_COMMAND_CHIP_ERASE,        EnumSpiOperationFullChipErase      },
+      { EnumSpiOpcodeRead,     SPI_COMMAND_READ_SFDP,         EnumSpiOperationReadData           },
+      { EnumSpiOpcodeWriteNoAddr,SPI_COMMAND_RPMC_OP1,          EnumSpiOperationOther              },
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_RPMC_OP2,          EnumSpiOperationReadData           },
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_Enter_4Byte_Addr,  EnumSpiOperationOther              },
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_Exit_4Byte_Addr,   EnumSpiOperationOther              }
+    },
+    0,
+    0x2000000   // BIOS image size in flash
+  }
+};
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.h
new file mode 100644
index 0000000000..fa7a7fec27
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/SpiFlashDevice.h
@@ -0,0 +1,62 @@
+/** @file
+  Implements SpiFlashDevice.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_FLASH_DEVICE_H_
+#define SPI_FLASH_DEVICE_H_
+
+#include <PiDxe.h>
+#include <Protocol/Spi.h>
+#include <Protocol/SpiCommon.h>
+
+//
+// Supported SPI Flash Devices
+//
+typedef enum {
+  EnumSpiFlashW25Q256JW,
+  EnumSpiFlashMax
+} SPI_FLASH_TYPES_SUPPORTED;
+
+// Flash Device commands
+//
+// If a supported device uses a command different from the list below, a device specific command
+// will be defined just below it's JEDEC id section.
+//
+#define SPI_COMMAND_WRITE             0x02
+#define SPI_COMMAND_WRITE_AAI         0xAD
+#define SPI_COMMAND_READ              0x03
+#define SPI_COMMAND_ERASE             0x20
+#define SPI_COMMAND_WRITE_DISABLE     0x04
+#define SPI_COMMAND_READ_S            0x05
+#define SPI_COMMAND_WRITE_ENABLE      0x06
+#define SPI_COMMAND_READ_ID           0xAB
+#define SPI_COMMAND_JEDEC_ID          0x9F
+#define SPI_COMMAND_WRITE_S_EN        0x50
+#define SPI_COMMAND_WRITE_S           0x01
+#define SPI_COMMAND_CHIP_ERASE        0xC7
+#define SPI_COMMAND_BLOCK_ERASE       0xD8
+#define SPI_COMMAND_READ_SFDP         0x5A
+#define SPI_COMMAND_RPMC_OP1          0x9B
+#define SPI_COMMAND_RPMC_OP2          0x96
+#define SPI_COMMAND_Enter_4Byte_Addr  0xB7
+#define SPI_COMMAND_Exit_4Byte_Addr   0xE9
+
+//
+// Winbond 256Mbit parts
+//
+#define SF_VENDOR_ID_WINBOND     0xEF
+#define SF_DEVICE_ID1_W25Q256JW  0x19          // Capacity 256Mbit
+#define SF_DEVICE_ID0_W25Q256JW  0x60
+
+//
+// index for prefix opcodes
+//
+#define SPI_WREN_INDEX  0                     // Prefix Opcode 0: SPI_COMMAND_WRITE_ENABLE
+#define SPI_EWSR_INDEX  1                     // Prefix Opcode 1: SPI_COMMAND_WRITE_S_EN
+#define BIOS_CTRL       0xDC
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.c
new file mode 100644
index 0000000000..0497509d03
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.c
@@ -0,0 +1,671 @@
+/** @file
+  Platform Flash Access library.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include  "UDKFlashUpdate.h"
+
+EFI_SPI_PROTOCOL  *mSpiProtocol = NULL;
+UINT32            mFlashAreaBaseAddress;
+UINTN             mBiosSize;
+UINTN             mBlockSize;
+
+/**
+  Input the BeginTimeValue and EndTimeValue, return the spent time(seconds).
+
+  @param[in] BeginTimeValue      The begin time value read by AsmReadTsc().
+  @param[in] EndTimeValue        The end time value read by AsmReadTsc().
+
+  @retval  -1                    An error occurred.
+  @retval  other                 The seconds value.
+
+**/
+STATIC
+INT64
+EFIAPI
+GetSpentTime (
+  IN  UINT64  EndTimeValue,
+  IN  UINT64  BeginTimeValue
+  )
+{
+  if (EndTimeValue >= BeginTimeValue) {
+    return (DivU64x32 (GetTimeInNanoSecond (EndTimeValue - BeginTimeValue), 1000000000));
+  } else {
+    Print (L"!!!ERROR: Wrong time\n");
+    return (-1);
+  }
+}
+
+/**
+  Read 'ReadAddress|NumBytes' of the flash chip, and saved into 'ReadFlash.bin'
+
+  @param[in] ReadAddress    Read address base in flash chip.
+  @param[in] NumBytes       Read number of bytes.
+
+  @retval  0                Flash read exited normally.
+  @retval  Other            An error occurred.
+
+**/
+UINTN
+EFIAPI
+FlashFdRead (
+  IN  UINTN   ReadAddress,
+  IN  UINTN   NumBytes,
+  IN  CHAR16  *FileName
+  )
+{
+  EFI_STATUS         Status;
+  VOID               *Buffer;
+  SHELL_FILE_HANDLE  FileHandle;
+
+  Print (L"\nRead flash chip and saved into %s ...\n", FileName);
+
+  Buffer = AllocateZeroPool (NumBytes);
+  if (NULL == Buffer) {
+    Print (L"!!!ERROR: Allocate pool fail ...\n");
+    return (1);
+  }
+
+  Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+  if (EFI_ERROR (Status)) {
+    Print (L"!!!ERROR: Open file %s %r\n", FileName, Status);
+    FreePool (Buffer);
+    return (1);
+  }
+
+  CopyMem ((UINT8 *)Buffer, (UINT8 *)(ReadAddress + mFlashAreaBaseAddress), NumBytes);
+  Status = ShellWriteFile (FileHandle, &NumBytes, Buffer);
+  if (EFI_ERROR (Status)) {
+    Print (L"!!!ERROR: Write file %s %r\n", FileName, Status);
+    FreePool (Buffer);
+    ShellCloseFile (&FileHandle);
+    return (1);
+  }
+
+  FreePool (Buffer);
+  ShellCloseFile (&FileHandle);
+
+  return (0);
+}
+
+/**
+  Erase 'EraseAddress|NumBytes' in flash chip, and skip the block all '0xFF'.
+
+  @param[in] EraseAddress                               Erase address base.
+  @param[in] NumBytes                             Erase number of bytes.
+
+  @retval  0                                                          Flash erase exited normally.
+  @retval  Other                                                    An error occurred.
+
+**/
+UINTN
+EFIAPI
+FlashFd64KErase (
+  IN  UINTN  EraseAddress,
+  IN  UINTN  NumBytes
+  )
+{
+  EFI_STATUS  Status;
+  // UINTN           Index;
+  UINT8  *Buffer;
+
+  Print (L"\nErase flash chip ");
+
+  Buffer = AllocateZeroPool (NumBytes);
+  if (NULL == Buffer) {
+    Print (L"!!!ERROR: Allocate fail ...\n");
+    return (1);
+  }
+
+  CopyMem (Buffer, (UINT8 *)(EraseAddress + mFlashAreaBaseAddress), NumBytes);
+
+  for ( ; EraseAddress < NumBytes; EraseAddress += mBlockSize) {
+    Status = mSpiProtocol->Execute (
+                             mSpiProtocol,
+                             SPI_OPCODE_ERASE_INDEX,              // OpcodeIndex
+                             0,                                   // PrefixOpcodeIndex
+                             FALSE,                               // DataCycle
+                             TRUE,                                // Atomic
+                             TRUE,                                // ShiftOut
+                             EraseAddress,                        // Address
+                             0,                                   // Data Number
+                             NULL,
+                             EnumSpiRegionBios                    // SPI_REGION_TYPE
+                             );
+    Print (L"Erase address = 0x%x, Erase %r\n", EraseAddress, Status);
+    if (EFI_ERROR (Status)) {
+      FreePool (Buffer);
+      Print (L"!!!ERROR: Erase flash %r\n", Status);
+      return (1);
+    }
+  }
+
+  FreePool (Buffer);
+  AsmWbinvd ();
+
+  return (0);
+}
+
+/**
+  Write 'WriteAddress|NumBytes' in flash chip and skip the block all '0xFF'.
+
+  @param[in] WriteAddress             Write address base in flash chip.
+  @param[in] NumBytes                 Write number of bytes.
+  @param[in] Buffer                   Point to contents going to write into flash chip.
+
+  @retval  0                          Flash write exited normally.
+  @retval  Other                      An error occurred.
+
+**/
+UINTN
+EFIAPI
+FlashFdWrite (
+  IN  UINTN  WriteAddress,
+  IN  UINTN  NumBytes,
+  IN  UINT8  *Buffer
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Index;
+
+  Print (L"\nWrite flash chip ");
+
+  for ( ; WriteAddress < NumBytes; WriteAddress += mBlockSize) {
+    for (Index = 0; Index < mBlockSize; Index++) {
+      if (0xFF != *(Buffer + Index)) {
+        Print (L"FlashFdWrite WriteAddress= 0x%x\n", WriteAddress);
+        Status = mSpiProtocol->Execute (
+                                 mSpiProtocol,
+                                 SPI_OPCODE_WRITE_INDEX,    // OpcodeIndex
+                                 0,                         // PrefixOpcodeIndex
+                                 TRUE,                      // DataCycle
+                                 TRUE,                      // Atomic
+                                 TRUE,                      // ShiftOut
+                                 WriteAddress,              // Address
+                                 (UINT32)mBlockSize,        // Data Number
+                                 Buffer,
+                                 EnumSpiRegionBios
+                                 );
+        if (EFI_ERROR (Status)) {
+          Print (L"!!!ERROR: Write flash %r\n", Status);
+          return (1);
+        } else {
+          Print (L".");
+        }
+
+        break;
+      }
+    }
+
+    Buffer += mBlockSize;
+  }
+
+  Print (L"\nWrite flash chip success\n");
+  AsmWbinvd ();
+
+  return (0);
+}
+
+/**
+  Verify the binary in flash chip and the source binary use checksum.
+
+  @param[in] BaseAddress              Write address base in memory.
+  @param[in] NumBytes                 Write total number of bytes.
+  @param[in] Sourcefile               Point to contents writed into flash chip.
+
+  @retval  0                          Flash verify exited normally.
+  @retval  Other                      An error occurred.
+
+**/
+UINTN
+EFIAPI
+FlashFdVerify (
+  IN  UINTN  BaseAddress,
+  IN  UINTN  NumBytes,
+  IN  VOID   *Sourcefile
+  )
+{
+  UINT8   *Buffer;
+  UINT32  Index;
+  UINT32  ChecksumSourceFile;
+  UINT32  ChecksumFlash;
+
+  Print (L"\n");
+
+  ChecksumSourceFile = 0;
+  ChecksumFlash      = 0;
+
+  Buffer = AllocateZeroPool (NumBytes);
+  if (NULL == Buffer) {
+    Print (L"!!!ERROR: Allocate fail ...\n");
+    return (1);
+  }
+
+  CopyMem (Buffer, (UINT8 *)(BaseAddress + mFlashAreaBaseAddress), NumBytes);
+  for (Index = 0; Index < NumBytes; Index++) {
+    ChecksumFlash      += *(UINT8 *)(Buffer + Index);
+    ChecksumSourceFile += *((UINT8 *)Sourcefile + Index);
+  }
+
+  Print (L"Flash checksum: 0x%x, Source File checksum: 0x%x\n", ChecksumFlash, ChecksumSourceFile);
+
+  if (ChecksumSourceFile == ChecksumFlash) {
+    Print (L"Verify success\n");
+  } else {
+    Print (L"!!!ERROR: Verify fail\n");
+    FreePool (Buffer);
+    return (1);
+  }
+
+  FreePool (Buffer);
+
+  return (0);
+}
+
+/**
+  Initialize.
+
+  @retval  0                          Flash erase exited normally.
+  @retval  Other                      An error occurred.
+
+**/
+UINTN
+EFIAPI
+Initialize (
+  IN  UINT8  *Index
+  )
+{
+  EFI_STATUS    Status;
+  UINT8         FlashIndex;
+  UINT8         FlashID[3];
+  SPI_INSTANCE  *SpiInstance;
+
+  mSpiProtocol = NULL;
+
+  Status = gBS->LocateProtocol (&gEfiSpiProtocolGuid, NULL, (VOID **)&mSpiProtocol);
+  if (EFI_ERROR (Status)) {
+    Print (L"!!!ERROR: Locate SpiProtocol %r\n", Status);
+    FreePool (mSpiProtocol);
+    return (1);
+  }
+
+  //
+  // attempt to identify flash part and initialize spi table
+  //
+  for (FlashIndex = 0; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
+    Status = mSpiProtocol->Init (
+                             mSpiProtocol
+                             );
+    if (!EFI_ERROR (Status)) {
+      //
+      // read vendor/device IDs to check if flash device is supported
+      //
+      Status = mSpiProtocol->Execute (
+                               mSpiProtocol,
+                               SPI_OPCODE_JEDEC_ID_INDEX,
+                               SPI_WREN_INDEX,
+                               TRUE,
+                               FALSE,
+                               FALSE,
+                               0,
+                               3,
+                               FlashID,
+                               EnumSpiRegionAll
+                               );
+      if (EFI_ERROR (Status)) {
+        return (1);
+      } else {
+        if ((FlashID[0] == mSpiInitTable[FlashIndex].VendorId) &&
+            (FlashID[1] == mSpiInitTable[FlashIndex].DeviceId0) &&
+            (FlashID[2] == mSpiInitTable[FlashIndex].DeviceId1))
+        {
+          Print (
+            L"Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x\n",
+            FlashID[0],
+            FlashID[1],
+            FlashID[2]
+            );
+          *Index = FlashIndex;
+          break;
+        }
+      }
+    }
+  }
+
+  SpiInstance           = SPI_INSTANCE_FROM_SPIPROTOCOL (mSpiProtocol);
+  mBiosSize             = SpiInstance->SpiInitTable.BiosSize;
+  mFlashAreaBaseAddress = (UINT32)(0x100000000 - mBiosSize);
+  mBlockSize            = SpiInstance->SpiInitTable.OpcodeMenu[SPI_OPCODE_ERASE_INDEX].Operation;
+  Print (L"BiosSize :0x%x, FlashAreaBaseAddress: 0x%x, Blocksize :0x%x\n", mBiosSize, mFlashAreaBaseAddress, mBlockSize);
+
+  return (0);
+}
+
+/**
+  Print out help information.
+
+**/
+STATIC
+VOID
+PrintHelpInfo (
+  VOID
+  )
+{
+  Print (L"Application to update flash chip. Depends on SpiProtocol.\nSupport flash chip: W25Q64FV/JV, W25Q64FW, MX25U6435F, MX25U12835F.\n\n");
+  Print (L"Usage: FLASHUPDATE option [filename]\n\n");
+  Print (L"Option:\n");
+  Print (L"  -help -h           This help message\n");
+  Print (L"  <file>             Specifies the name of the file to write into flash chip\n");
+  Print (L"  -v                 Display version information\n");
+  Print (L"  -r                 Read flash chip and saved into file\n\n");
+  Print (L"Filename:\n");
+  Print (L"                     Specifies the name of the file to save the contents read\n                     \
+from flash chip, just need when read flash chip.\n\n");
+}
+
+/**
+  Parse command in shell.
+
+  @param[in] Num           The number of items in Str.
+  @param[in] Str           Array of pointers to strings.
+
+  @retval  0               The application exited normally.
+  @retval  2               Read flash chip and save into file.
+  @retval  Other           An error occurred.
+
+**/
+STATIC
+UINTN
+EFIAPI
+ShellCommandParse (
+  IN  UINTN   Num,
+  IN  CHAR16  **Str
+  )
+{
+  EFI_STATUS  Status;
+
+  if (Num < 2) {
+    Print (L"FlashUpdate: Too few argument\n\n");
+    PrintHelpInfo ();
+    return (1);
+  } else if (2 == Num) {
+    if (StrLen (Str[1]) == 0) {
+      Print (L"FlashUpdate: Too few argument\n\n");
+      PrintHelpInfo ();
+      return (1);
+    }
+
+    if ((Str[1])[0] == L'-') {
+      //
+      // Parse the arguments.
+      //
+      if (StrCmp (Str[1], L"-v") == 0) {
+        Print (L"FlashUpdate: Version 20230527\n\n");
+        return (1);
+      }
+
+      if (StrCmp (Str[1], L"-r") == 0) {
+        Print (L"FlashUpdate: Too few argument\n\n");
+        PrintHelpInfo ();
+        return (1);
+      }
+
+      if ((StrCmp (Str[1], L"-help") == 0) || (StrCmp (Str[1], L"-h") == 0)) {
+        PrintHelpInfo ();
+        return (1);
+      } else {
+        Print (L"FlashUpdate: Illegal option: '%s'\n\n", Str[1]);
+        PrintHelpInfo ();
+        return (1);
+      }
+    }
+
+    Status = ShellIsFile (Str[1]);
+    if (EFI_ERROR (Status)) {
+      Print (L"FlashUpdate: %s is not a file\n\n", Str[1]);
+      PrintHelpInfo ();
+      return (1);
+    }
+  } else if (3 == Num) {
+    if ((Str[1])[0] == L'-') {
+      if (StrCmp (Str[1], L"-r") == 0) {
+        Print (L"Read flash chip\n");
+        return (2);
+      }
+    }
+
+    Print (L"FlashUpdate: Illegal argument: '%s %s'\n\n", Str[1], Str[2]);
+    PrintHelpInfo ();
+    return (1);
+  } else if (Num > 3) {
+    Print (L"FlashUpdate: Too many argument\n\n");
+    PrintHelpInfo ();
+    return (1);
+  }
+
+  return (0);
+}
+
+/**
+  UEFI application entry point which has an interface similar to a
+  standard C main function.
+
+  The ShellCEntryLib library instance wrappers the actual UEFI application
+  entry point and calls this ShellAppMain function.
+
+  @param[in] Argc          The number of items in Argv.
+  @param[in] Argv          Array of pointers to strings.
+
+  @retval  0               The application exited normally.
+  @retval  Other           An error occurred.
+
+**/
+INTN
+EFIAPI
+ShellAppMain (
+  IN  UINTN   Argc,
+  IN  CHAR16  **Argv
+  )
+{
+  VOID               *Buffer;
+  EFI_STATUS         Status;
+  SHELL_FILE_HANDLE  SourceHandle;
+  UINTN              SourceFileSize;
+  UINTN              BeginTimeValue;
+  UINTN              InitTimeValue;
+  UINTN              EraseTimeValue;
+  UINTN              WriteTimeValue;
+  UINTN              VerifyTimeValue;
+  UINTN              BaseAddress;
+  UINTN              NumBytes;
+  UINT32             Index;
+  UINT8              FlashIndex;
+
+  BeginTimeValue = AsmReadTsc ();
+  SourceHandle   = NULL;
+  Buffer         = NULL;
+
+  Status = Initialize (&FlashIndex);
+  if (0 != Status) {
+    Print (L"!!!ERROR: Initialize fail\n");
+    return (1);
+  }
+
+  BaseAddress = 0;
+  NumBytes    = mBiosSize; // Assign after mBiosSize init in Initialize
+
+  //
+  // Parse the command line.
+  //
+  Status = ShellCommandParse (Argc, Argv);
+  if (1 == Status) {
+    return (1);
+  } else if (2 == Status) {
+    Status = FlashFdRead (BaseAddress, NumBytes, Argv[2]);
+    if (0 != Status) {
+      Print (L"!!!ERROR: Read flash chip fail");
+      return (1);
+    }
+
+    Print (L"Read flash chip and saved into %s success\n", Argv[2]);
+    return (0);
+  }
+
+  //
+  // open source file
+  //
+  Status = ShellOpenFileByName (Argv[1], &SourceHandle, EFI_FILE_MODE_READ, 0);
+  if (EFI_ERROR (Status)) {
+    Print (L"!!!ERROR: Open file %s %r\n", Argv[1], Status);
+    return (1);
+  }
+
+  //
+  // get file size of source file
+  //
+  Status = ShellGetFileSize (SourceHandle, &SourceFileSize);
+  if (EFI_ERROR (Status)) {
+    Print (L"!!!ERROR: Read file %s size %r\n", Argv[1], Status);
+    if (NULL != SourceHandle) {
+      ShellCloseFile (&SourceHandle);
+    }
+
+    return (1);
+  }
+
+  Buffer = AllocateZeroPool (SourceFileSize);
+  if (NULL == Buffer) {
+    Print (L"!!!ERROR: Allocate pool fail ...\n");
+    if (NULL != SourceHandle) {
+      ShellCloseFile (&SourceHandle);
+    }
+
+    return (1);
+  }
+
+  Status = ShellReadFile (SourceHandle, &SourceFileSize, Buffer);
+  if (EFI_ERROR (Status)) {
+    Print (L"!!!ERROR: Read file %s %r\n", Argv[1], Status);
+    if (NULL != SourceHandle) {
+      ShellCloseFile (&SourceHandle);
+    }
+
+    if (NULL != Buffer) {
+      FreePool (Buffer);
+    }
+
+    return (1);
+  }
+
+  Print (
+    L"Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x\n",
+    mSpiInitTable[FlashIndex].VendorId,
+    mSpiInitTable[FlashIndex].DeviceId0,
+    mSpiInitTable[FlashIndex].DeviceId1
+    );
+
+  InitTimeValue = AsmReadTsc ();
+  Print (L"Init spent time: %d seconds\n", GetSpentTime (InitTimeValue, BeginTimeValue));
+
+  Print (L"Size of %s: 0x%x bytes, Flash size: 0x%x bytes\n", Argv[1], SourceFileSize, mBiosSize);
+  if (mBiosSize != SourceFileSize) {
+    Print (L"!!!ERROR: Bios size is not correct\n");
+    if (NULL != SourceHandle) {
+      ShellCloseFile (&SourceHandle);
+    }
+
+    if (NULL != Buffer) {
+      FreePool (Buffer);
+    }
+
+    return (1);
+  }
+
+  Status = FlashFd64KErase (BaseAddress, NumBytes);
+  if (0 != Status) {
+    Print (L"!!!ERROR: Erase falsh chip fail\n");
+    if (NULL != SourceHandle) {
+      ShellCloseFile (&SourceHandle);
+    }
+
+    if (NULL != Buffer) {
+      FreePool (Buffer);
+    }
+
+    return (1);
+  }
+
+  if (0 != Status) {
+    Print (L"!!!ERROR: Erase falsh chip fail\n");
+    if (NULL != SourceHandle) {
+      ShellCloseFile (&SourceHandle);
+    }
+
+    if (NULL != Buffer) {
+      FreePool (Buffer);
+    }
+
+    return (1);
+  }
+
+  EraseTimeValue = AsmReadTsc ();
+  Print (L"Erase spent time: %d seconds\n", GetSpentTime (EraseTimeValue, InitTimeValue));
+
+  Status = FlashFdWrite (BaseAddress, NumBytes, Buffer);
+  if (0 != Status) {
+    Print (L"!!!ERROR: Write falsh chip fail\n");
+    if (NULL != SourceHandle) {
+      ShellCloseFile (&SourceHandle);
+    }
+
+    if (NULL != Buffer) {
+      FreePool (Buffer);
+    }
+
+    return (1);
+  }
+
+  WriteTimeValue = AsmReadTsc ();
+  Print (L"\nWrite spent time: %d seconds\n", GetSpentTime (WriteTimeValue, EraseTimeValue));
+
+  Status = FlashFdVerify (BaseAddress, NumBytes, (UINT8 *)Buffer);
+  if (0 != Status) {
+    Print (L"!!!ERROR: Verify falsh chip fail\n");
+    if (NULL != SourceHandle) {
+      ShellCloseFile (&SourceHandle);
+    }
+
+    if (NULL != Buffer) {
+      FreePool (Buffer);
+    }
+
+    return (1);
+  }
+
+  VerifyTimeValue = AsmReadTsc ();
+  Print (L"\nWrite flash chip success!\n");
+  Print (L"--------------------------------------------------\n");
+  Print (L"Total spent time: %d seconds\n", GetSpentTime (VerifyTimeValue, BeginTimeValue));
+
+  if (NULL != SourceHandle) {
+    ShellCloseFile (&SourceHandle);
+  }
+
+  if (NULL != Buffer) {
+    FreePool (Buffer);
+  }
+
+  Print (L"\nReady to restart ");
+  for (Index = 0; Index < 4; Index++) {
+    MicroSecondDelay (1000000); // delay 1 second
+    Print (L".");
+  }
+
+  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+
+  return (0);
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.h
new file mode 100644
index 0000000000..ed15a4489a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.h
@@ -0,0 +1,48 @@
+/** @file
+  Implements UDKFlashUpdate.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef UDK_FLASH_UPDATE_H_
+#define UDK_FLASH_UPDATE_H_
+
+#include <Uefi.h>
+
+#include <Library/UefiLib.h>
+#include <Library/ShellCEntryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/TimerLib.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/Shell.h>
+#include <Protocol/Spi.h>
+#include <Protocol/CpuIo2.h>
+#include <Protocol/SpiCommon.h>
+
+#include "SpiFlashDevice.h"
+
+#define SPI_OPCODE_JEDEC_ID_INDEX           0
+#define SPI_OPCODE_WRITE_S_INDEX            1
+#define SPI_OPCODE_WRITE_INDEX              2
+#define SPI_OPCODE_READ_INDEX               3
+#define SPI_OPCODE_ERASE_INDEX              4
+#define SPI_OPCODE_READ_S_INDEX             5
+#define SPI_OPCODE_CHIP_ERASE_INDEX         6
+#define SPI_OPCODE_READ_SFDP_INDEX          7
+#define SPI_COMMAND_RPMC_OP1_INDEX          8
+#define SPI_COMMAND_RPMC_OP2_INDEX          9
+#define SPI_COMMAND_Enter_4Byte_Addr_INDEX  10
+#define SPI_COMMAND_Exit_4Byte_Addr_INDEX   11
+
+extern SPI_INIT_TABLE        mSpiInitTable[];
+extern EFI_RUNTIME_SERVICES  *gRT;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.inf
new file mode 100644
index 0000000000..8f055f3925
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Application/UDKFlashUpdate/UDKFlashUpdate.inf
@@ -0,0 +1,51 @@
+## @file
+#  UDK Flash update
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010006
+  BASE_NAME                      = UDKFlashUpdate
+  FILE_GUID                      = a912f198-7f0e-4803-b908-b757b806ec83
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 0.1
+  ENTRY_POINT                    = ShellCEntryLib
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF
+#
+
+[Sources]
+  UDKFlashUpdate.c
+  UDKFlashUpdate.h
+  SpiFlashDevice.c
+  SpiFlashDevice.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ShellPkg/ShellPkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiLib
+  ShellCEntryLib
+  MemoryAllocationLib
+  ShellLib
+  UefiBootServicesTableLib
+  PcdLib
+  BaseMemoryLib
+  BaseLib
+  TimerLib
+
+[Protocols]
+  gEfiSpiProtocolGuid        # CONSUME
+
+[FixedPcd]
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress
+
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114584): https://edk2.groups.io/g/devel/message/114584
Mute This Topic: https://groups.io/mt/103975447/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 09/32] AMD/VanGoghBoard: Check in Flash_AB
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (7 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 08/32] AMD/VanGoghBoard: Check in UDKFlashUpdate Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 10/32] AMD/VanGoghBoard: Check in FlashUpdate Zhai, MingXin (Duke) via groups.io
                   ` (23 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="yes", Size: 366 bytes --]



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114585): https://edk2.groups.io/g/devel/message/114585
Mute This Topic: https://groups.io/mt/103975449/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 10/32] AMD/VanGoghBoard: Check in FlashUpdate
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (8 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 09/32] AMD/VanGoghBoard: Check in Flash_AB Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 11/32] AMD/VanGoghBoard: Check in FvbServices Zhai, MingXin (Duke) via groups.io
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial FlashUpdate module for Chachani platform flash IC.
  It provides mEfiSpiFlashUpdateProtocol for other module to access flash.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../FlashUpdate/FlashUpdateCommon.h           | 143 +++++
 .../FlashUpdate/FlashUpdateSmm.c              | 512 ++++++++++++++++++
 .../FlashUpdate/FlashUpdateSmm.h              | 123 +++++
 .../FlashUpdate/FlashUpdateSmm.inf            |  59 ++
 .../FlashUpdate/FlashUpdateSmmRuntimeDxe.c    | 407 ++++++++++++++
 .../FlashUpdate/FlashUpdateSmmRuntimeDxe.inf  |  48 ++
 .../VanGoghCommonPkg/FlashUpdate/PcRtc.h      | 375 +++++++++++++
 7 files changed, 1667 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateCommon.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/PcRtc.h

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateCommon.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateCommon.h
new file mode 100644
index 0000000000..77967f1f26
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateCommon.h
@@ -0,0 +1,143 @@
+/** @file
+  Implements AMD FlashUpdateCommon.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FLASH_UPDATE_COMMON_H_
+#define FLASH_UPDATE_COMMON_H_
+
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+#include <Protocol/SpiFlashUpdate.h>
+#include <Protocol/SmmCommunication.h>
+
+#include <Uefi/UefiAcpiDataTable.h>
+#include <Uefi/UefiSpec.h>
+
+#include <Guid/EventGroup.h>
+
+#define SPI_SMM_COMM_ID_GET_FLASH_SIZE_BLOCK_SIZE  0x0       // ID for get flash size and block size
+#define SPI_SMM_COMM_ID_READ_FLASH                 0x1       // ID for Read Flash
+#define SPI_SMM_COMM_ID_WRITE_FALSH                0x2       // ID for Write Flash
+#define SPI_SMM_COMM_ID_ERASE_FALSH                0x3       // ID for Erase Flash
+
+//
+// SMM communication common buffer
+//
+typedef struct _FLASH_UPDATE_SMM_COMMUNICATION_CMN {
+  UINT32    id;                     // Function ID of smm communication buffer
+} FLASH_UPDATE_SMM_COMMUNICATION_CMN;
+
+#pragma pack(1)
+
+//
+// SMM communication common buffer
+//
+typedef struct _SMM_COMM_RWE_FLASH {
+  UINT32        id;                          // ID of smm communication buffer
+  UINTN         FlashAddress;                // Flash devicd physical flash address
+  UINTN         NumBytes;                    // Number in byte
+  EFI_STATUS    ReturnStatus;                // Return status
+  UINT8         Buffer[1];                   // Buffer start
+} SMM_COMM_RWE_FLASH;
+
+//
+// SMM communication common buffer
+//
+typedef struct _SMM_COMM_GET_FLASH_SIZE_BLOCK_SIZE {
+  UINT32        id;                           // ID of smm communication buffer
+  UINTN         FlashSize;                    // Flash size
+  UINTN         BlockSize;                    // Block size of flash device
+  EFI_STATUS    ReturnStatus;                 // Return status
+} SMM_COMM_GET_FLASH_SIZE_BLOCK_SIZE;
+
+#pragma pack()
+
+#define SMM_COMMUNICATE_HEADER_SIZE  (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))
+#define SMM_COMM_RWE_FLASH_SIZE      (OFFSET_OF (SMM_COMM_RWE_FLASH, Buffer))
+
+/**
+  Read data from flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[out] Buffer                      Buffer contain the read data.
+
+  @retval EFI_SUCCESS                     Read successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+SfuProtocolFlashFdRead (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes,
+  OUT VOID   *Buffer
+  );
+
+/**
+  Erase flash region according to input in a block size.
+
+  @param[in] FlashAddress                 Physical flash address.
+  @param[in] NumBytes                     Number in Byte, a block size in flash device.
+
+  @retval EFI_SUCCESS                     Erase successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+SfuProtocolFlashFdErase (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes
+  );
+
+/**
+  Write data to flash device.
+
+  Write Buffer(FlashAddress|NumBytes) to flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[in]  Buffer                      Buffer contain the write data.
+
+  @retval EFI_SUCCESS                     Write successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+SfuProtocolFlashFdWrite (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes,
+  IN  UINT8  *Buffer
+  );
+
+/**
+  Get flash device size and flash block size.
+
+  @param[out] FlashSize                   Pointer to the size of flash device.
+  @param[out] BlockSize                   Pointer to the size of block in flash device.
+
+  @retval EFI_SUCCESS                     Get successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+
+**/
+EFI_STATUS
+EFIAPI
+SfuProtocolGetFlashSizeBlockSize (
+  OUT  UINTN  *FlashSize,
+  OUT  UINTN  *BlockSize
+  );
+
+#endif // _FLASH_UPDATE_COMMON_H_
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.c
new file mode 100644
index 0000000000..42991295d7
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.c
@@ -0,0 +1,512 @@
+/** @file
+  Implements AMD FlashUpdateSmm.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "FlashUpdateSmm.h"
+
+#define PM1_EN_HIGH_BYTE  0x03
+#define RTC_EVENT_ENABLE  0x04
+#define ACPIMMIO16(x)  (*(volatile UINT16*)(UINTN)(x))
+#define ACPI_MMIO_BASE    0xFED80000ul
+#define ACPI_PM1_EVT_BLK  0x60
+#define ACPI_PM1_CNT_BLK  0x62
+#define PMIO_BASE         0x300                     // DWORD
+#define SUS_S3            0x0C00U                   // S3
+#define SUS_S5            0x1400U                   // S5
+#define SLP_TYPE          0x1C00U                   // MASK
+#define SLP_EN            0x2000U                   // BIT13
+
+EFI_SPI_PROTOCOL  *mSmmSpiProtocol = NULL;
+UINTN             mFlashAreaBaseAddress;
+UINTN             mFlashSize;
+UINTN             mBlockSize;
+
+EFI_SMM_SPI_FLASH_UPDATE_PROTOCOL  mEfiSmmSpiFlashUpdateProtocol = {
+  FlashUpdateServiceFlashFdRead,
+  FlashUpdateServiceFlashFdErase,
+  FlashUpdateServiceFlashFdWrite,
+  FlashUpdateServiceGetFlashSizeBlockSize,
+};
+
+/**
+  Read data from flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[out] Buffer                      Buffer contain the read data.
+
+  @retval EFI_SUCCESS                     Read successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceFlashFdRead (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes,
+  OUT VOID   *Buffer
+  )
+{
+  if ((FlashAddress >= mFlashSize) || (NumBytes == 0) || (NumBytes > mFlashSize) ||
+      (Buffer == NULL) || (FlashAddress + NumBytes > mFlashSize))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyMem (Buffer, (UINT8 *)(FlashAddress + mFlashAreaBaseAddress), NumBytes);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Erase flash region according to input in a block size.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte, a block size in flash device.
+
+  @retval EFI_SUCCESS                     Erase successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceFlashFdErase (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes
+  )
+{
+  EFI_STATUS  Status;
+
+  if ((FlashAddress >= mFlashSize) || (NumBytes == 0) || (NumBytes > mFlashSize) ||
+      (FlashAddress + NumBytes > mFlashSize))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (mSmmSpiProtocol == NULL) {
+    DEBUG ((DEBUG_ERROR, "mSmmSpiProtocol = NULL\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  Status = mSmmSpiProtocol->Execute (
+                              mSmmSpiProtocol,
+                              SPI_OPCODE_ERASE_INDEX,  // OpcodeIndex
+                              0,                       // PrefixOpcodeIndex
+                              FALSE,                   // DataCycle
+                              TRUE,                    // Atomic
+                              TRUE,                    // ShiftOut
+                              FlashAddress,            // Address
+                              0,                       // Data Number
+                              NULL,                    // Buffer
+                              EnumSpiRegionBios        // SpiRegionType
+                              );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "!!!ERROR: Erase flash %r\n", Status));
+    return Status;
+  }
+
+  AsmWbinvd ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Write data to flash device.
+
+  Write Buffer(FlashAddress|NumBytes) to flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[in]  Buffer                      Buffer contain the write data.
+
+  @retval EFI_SUCCESS                     Write successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceFlashFdWrite (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes,
+  IN  UINT8  *Buffer
+  )
+{
+  EFI_STATUS  Status;
+
+  if ((FlashAddress >= mFlashSize) || (NumBytes == 0) || (NumBytes > mFlashSize) || (Buffer == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (FlashAddress + NumBytes > mFlashSize) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (mSmmSpiProtocol == NULL) {
+    DEBUG ((DEBUG_ERROR, "mSmmSpiProtocol = NULL\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  Status = mSmmSpiProtocol->Execute (
+                              mSmmSpiProtocol,
+                              SPI_OPCODE_WRITE_INDEX, // OpcodeIndex
+                              0,                      // PrefixOpcodeIndex
+                              TRUE,                   // DataCycle
+                              TRUE,                   // Atomic
+                              TRUE,                   // ShiftOut
+                              FlashAddress,           // Address
+                              (UINT32)NumBytes,       // Data Number
+                              Buffer,                 // Buffer
+                              EnumSpiRegionBios       // Spi Region Type
+                              );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "!!!ERROR: Write flash %r\n", Status));
+    return Status;
+  }
+
+  AsmWbinvd ();
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get flash device size and flash block size.
+
+  @param[out] FlashSize                   Pointer to the size of flash device.
+  @param[out] BlockSize                   Pointer to the size of block in flash device.
+
+  @retval EFI_SUCCESS                     Get successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceGetFlashSizeBlockSize (
+  OUT  UINTN  *FlashSize,
+  OUT  UINTN  *BlockSize
+  )
+{
+  if ((FlashSize == 0) || (BlockSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *FlashSize = mFlashSize;
+  *BlockSize = mBlockSize;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Communication service SMI Handler entry.
+
+  This SMI handler provides services for the update flash routines.
+
+  @param[in]      DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
+  @param[in]      RegisterContext Points to an optional handler context which was specified when the
+                                 handler was registered.
+  @param[in, out] CommBuffer     A pointer to a collection of data in memory that will
+                                 be conveyed from a non-SMM environment into an SMM environment.
+  @param[in, out] CommBufferSize The size of the CommBuffer.
+
+  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers
+                                              should still be called.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceHandler (
+  IN     EFI_HANDLE  DispatchHandle,
+  IN     CONST VOID  *RegisterContext,
+  IN OUT VOID        *CommBuffer,
+  IN OUT UINTN       *CommBufferSize
+  )
+{
+  EFI_STATUS                          Status;
+  FLASH_UPDATE_SMM_COMMUNICATION_CMN  *Buffer;
+  SMM_COMM_RWE_FLASH                  *RweBuffer;
+  SMM_COMM_GET_FLASH_SIZE_BLOCK_SIZE  *GetFlashSizeBlockSizeBuffer;
+
+  //
+  // If input is invalid, stop processing this SMI
+  //
+  if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {
+    DEBUG ((DEBUG_ERROR, "!!!ERROR: FlashUpdateServiceHandler: Invalid parameter!\n"));
+    return EFI_SUCCESS;
+  }
+
+  if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, *CommBufferSize)) {
+    DEBUG ((DEBUG_ERROR, "!!!ERROR: FlashUpdateServiceHandler: SMM communication buffer in SMRAM or overflow!\n"));
+    return EFI_SUCCESS;
+  }
+
+  GetFlashSizeBlockSizeBuffer = NULL;
+  Buffer                      = (FLASH_UPDATE_SMM_COMMUNICATION_CMN *)CommBuffer;
+  RweBuffer                   = (SMM_COMM_RWE_FLASH *)CommBuffer;
+
+  switch (Buffer->id) {
+    case SPI_SMM_COMM_ID_GET_FLASH_SIZE_BLOCK_SIZE:
+      GetFlashSizeBlockSizeBuffer               = (SMM_COMM_GET_FLASH_SIZE_BLOCK_SIZE *)CommBuffer;
+      GetFlashSizeBlockSizeBuffer->ReturnStatus = EFI_SUCCESS;
+      GetFlashSizeBlockSizeBuffer->FlashSize    = mFlashSize;
+      GetFlashSizeBlockSizeBuffer->BlockSize    = mBlockSize;
+      break;
+
+    case SPI_SMM_COMM_ID_READ_FLASH:
+      Status = mEfiSmmSpiFlashUpdateProtocol.Read (
+                                               RweBuffer->FlashAddress,
+                                               RweBuffer->NumBytes,
+                                               RweBuffer->Buffer
+                                               );
+      RweBuffer->ReturnStatus = Status;
+      break;
+
+    case SPI_SMM_COMM_ID_WRITE_FALSH:
+      Status = mEfiSmmSpiFlashUpdateProtocol.Write (
+                                               RweBuffer->FlashAddress,
+                                               RweBuffer->NumBytes,
+                                               RweBuffer->Buffer
+                                               );
+      RweBuffer->ReturnStatus = Status;
+      break;
+
+    case SPI_SMM_COMM_ID_ERASE_FALSH:
+      Status = mEfiSmmSpiFlashUpdateProtocol.Erase (
+                                               RweBuffer->FlashAddress,
+                                               RweBuffer->NumBytes
+                                               );
+      RweBuffer->ReturnStatus = Status;
+      break;
+
+    default:
+      ASSERT (FALSE);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Read RTC through its registers  using IO access.
+
+  @param  Address   Address offset of RTC. It is recommended to use
+                    macros such as RTC_ADDRESS_SECONDS.
+  @param  Data      The content you want to write into RTC.
+
+**/
+STATIC
+UINT8
+IoRtcRead (
+  IN  UINT8  Address
+  )
+{
+  IoWrite8 (0x70, Address);
+  return IoRead8 (0x71);
+}
+
+/**
+  Write RTC through its registers  using IO access.
+
+  @param  Address   Address offset of RTC. It is recommended to use
+                    macros such as RTC_ADDRESS_SECONDS.
+  @param  Data      The content you want to write into RTC.
+
+**/
+STATIC
+VOID
+IoRtcWrite (
+  IN  UINT8  Address,
+  IN  UINT8  Data
+  )
+{
+  IoWrite8 (0x70, Address);
+  IoWrite8 (0x71, Data);
+}
+
+/**
+  Write RTC through its registers  using IO access.
+
+  @param  Address   Address offset of RTC. It is recommended to use
+                    macros such as RTC_ADDRESS_SECONDS.
+  @param  Data      The content you want to write into RTC.
+
+**/
+VOID
+EnableRtcWakeup (
+  IN UINT16  AcpiBaseAddr,
+  IN UINT8   WakeAfter
+  )
+{
+  volatile RTC_REGISTER_B  RtcRegisterB;
+
+  RtcRegisterB.Data = IoRtcRead (RTC_ADDRESS_REGISTER_B);
+  UINT8  CurrentSecond = IoRtcRead (RTC_ADDRESS_SECONDS);
+  UINT8  CurrentMinute = IoRtcRead (RTC_ADDRESS_MINUTES);
+  UINT8  CurrentHour   = IoRtcRead (RTC_ADDRESS_HOURS);
+
+  if (!(RtcRegisterB.Bits.Dm)) {
+    CurrentSecond = BcdToDecimal8 (CurrentSecond);
+    CurrentMinute = BcdToDecimal8 (CurrentMinute);
+    CurrentHour   = BcdToDecimal8 (CurrentHour);
+  }
+
+  CurrentSecond += WakeAfter;
+  CurrentMinute += CurrentSecond/60;
+  CurrentHour   += CurrentMinute/60;
+
+  CurrentSecond %= 60;
+  CurrentMinute %= 60;
+  CurrentHour   %= 24;
+
+  if (!(RtcRegisterB.Bits.Dm)) {
+    CurrentSecond = DecimalToBcd8 (CurrentSecond);
+    CurrentMinute = DecimalToBcd8 (CurrentMinute);
+    CurrentHour   = DecimalToBcd8 (CurrentHour);
+  }
+
+  IoRtcWrite (RTC_ADDRESS_SECONDS_ALARM, CurrentSecond);
+  IoRtcWrite (RTC_ADDRESS_MINUTES_ALARM, CurrentMinute);
+  IoRtcWrite (RTC_ADDRESS_HOURS_ALARM, CurrentHour);
+  IoRtcRead (RTC_ADDRESS_REGISTER_C);
+
+  RtcRegisterB.Data     = IoRtcRead (RTC_ADDRESS_REGISTER_B);
+  RtcRegisterB.Bits.Aie = 1;
+  IoRtcWrite (RTC_ADDRESS_REGISTER_B, RtcRegisterB.Data);
+
+  UINT8  RtcSts = IoRead8 (AcpiBaseAddr);
+
+  RtcSts |= 0x400;
+  IoWrite8 (AcpiBaseAddr, RtcSts);
+
+  UINT8  RtcEn = IoRead8 (AcpiBaseAddr + PM1_EN_HIGH_BYTE);
+
+  RtcEn |= RTC_EVENT_ENABLE;
+  IoWrite8 (AcpiBaseAddr + PM1_EN_HIGH_BYTE, RtcEn);
+  return;
+}
+
+/**
+  Set Capsule S3 Flag SMI Handler.
+
+  This SMI handler provides services for marking capsule update.
+
+  @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
+  @param[in]     RegisterContext Points to an optional handler context which was specified when the
+                                 handler was registered.
+  @param[in, out] CommBuffer     A pointer to a collection of data in memory that will
+                                 be conveyed from a non-SMM environment into an SMM environment.
+  @param[in, out] CommBufferSize The size of the CommBuffer.
+
+  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers
+                                              should still be called.
+
+**/
+EFI_STATUS
+EFIAPI
+SetCapsuleS3FlagHandler (
+  IN     EFI_HANDLE  DispatchHandle,
+  IN     CONST VOID  *RegisterContext,
+  IN OUT VOID        *CommBuffer,
+  IN OUT UINTN       *CommBufferSize
+  )
+{
+  EFI_STATUS                     Status;
+  AMD_CAPSULE_SMM_HOOK_PROTOCOL  *AmdCapsuleSmmHookProtocol;
+
+  AmdCapsuleSmmHookProtocol = NULL;
+  Status                    = gSmst->SmmLocateProtocol (
+                                       &gAmdCapsuleSmmHookProtocolGuid,
+                                       NULL,
+                                       (VOID **)&AmdCapsuleSmmHookProtocol
+                                       );
+  if (!EFI_ERROR (Status)) {
+    AmdCapsuleSmmHookProtocol->Hook (0);
+  }
+
+  DEBUG ((DEBUG_INFO, "Entering S3 sleep.\n"));
+  // Transform system into S3 sleep state
+  EnableRtcWakeup (ACPIMMIO16 (ACPI_MMIO_BASE + PMIO_BASE + ACPI_PM1_EVT_BLK), 2);
+  UINTN   AcpiPm1CntBase = ACPIMMIO16 (ACPI_MMIO_BASE + PMIO_BASE + ACPI_PM1_CNT_BLK);
+  UINT16  PmCntl         = IoRead16 (AcpiPm1CntBase);
+
+  PmCntl = (PmCntl & ~SLP_TYPE) | SUS_S3 | SLP_EN;
+  IoWrite16 (AcpiPm1CntBase, PmCntl);
+  return Status;
+}
+
+/**
+  Smm Flash Update Driver main entry point.
+
+  Install the Smm Flash Update Protocol on a new handle. Register SMM flash update
+  SMI handler. Locate SmmSpiProtocol and init the flash device size and block size.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       Variable service successfully initialized.
+  @retval others            Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+  EFI_HANDLE    FlashUpdateRegisterHandle;
+  EFI_HANDLE    FlashUpdateInstallHandle;
+  SPI_INSTANCE  *SpiInstance;
+  EFI_HANDLE    SetCapsuleS3FlagHandle;
+
+  SpiInstance = NULL;
+
+  //
+  // Install the Smm Flash Update Protocol on a new handle
+  //
+  FlashUpdateInstallHandle = NULL;
+  Status                   = gSmst->SmmInstallProtocolInterface (
+                                      &FlashUpdateInstallHandle,
+                                      &gEfiSmmSpiFlashUpdateProtocolGuid,
+                                      EFI_NATIVE_INTERFACE,
+                                      &mEfiSmmSpiFlashUpdateProtocol
+                                      );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register SMM flash update SMI handler
+  //
+  FlashUpdateRegisterHandle = NULL;
+  Status                    = gSmst->SmiHandlerRegister (
+                                       FlashUpdateServiceHandler,
+                                       &gEfiSmmSpiFlashUpdateProtocolGuid,
+                                       &FlashUpdateRegisterHandle
+                                       );
+  ASSERT_EFI_ERROR (Status);
+
+  SetCapsuleS3FlagHandle = NULL;
+  Status                 = gSmst->SmiHandlerRegister (
+                                    SetCapsuleS3FlagHandler,
+                                    &gAmdSetCapsuleS3FlagGuid,
+                                    &SetCapsuleS3FlagHandle
+                                    );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gSmst->SmmLocateProtocol (
+                    &gEfiSmmSpiProtocolGuid,
+                    NULL,
+                    (VOID **)&mSmmSpiProtocol
+                    );
+  ASSERT_EFI_ERROR (Status);
+
+  SpiInstance           = SPI_INSTANCE_FROM_SPIPROTOCOL (mSmmSpiProtocol);
+  mFlashSize            = SpiInstance->SpiInitTable.BiosSize;
+  mFlashAreaBaseAddress = FixedPcdGet32 (PcdFlashAreaBaseAddress);
+  mBlockSize            = SpiInstance->SpiInitTable.OpcodeMenu[SPI_OPCODE_ERASE_INDEX].Operation;
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.h
new file mode 100644
index 0000000000..6019e635c5
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.h
@@ -0,0 +1,123 @@
+/** @file
+  Implements AMD FlashUpdateSmm.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FLASH_UPDATE_SMM_H_
+#define FLASH_UPDATE_SMM_H_
+
+#include <Library/SmmServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SmmMemLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/SpiFlashUpdate.h>
+#include <Protocol/SpiCommon.h>
+
+#include <Uefi/UefiBaseType.h>
+
+#include "FlashUpdateCommon.h"
+#include "PcRtc.h"
+
+/**
+  Read data from flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[out] Buffer                      Buffer contain the read data.
+
+  @retval EFI_SUCCESS                     Read successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceFlashFdRead (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes,
+  OUT VOID   *Buffer
+  );
+
+/**
+  Erase flash region according to input in a block size.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte, a block size in flash device.
+
+  @retval EFI_SUCCESS                     Erase successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceFlashFdErase (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes
+  );
+
+/**
+  Write data to flash device.
+
+  Write Buffer(FlashAddress|NumBytes) to flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[in]  Buffer                      Buffer contain the write data.
+
+  @retval EFI_SUCCESS                     Write successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceFlashFdWrite (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes,
+  IN  UINT8  *Buffer
+  );
+
+/**
+  Get flash device size and flash block size.
+
+  @param[out] FlashSize                   Pointer to the size of flash device.
+  @param[out] BlockSize                   Pointer to the size of block in flash device.
+
+  @retval EFI_SUCCESS                     Get successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateServiceGetFlashSizeBlockSize (
+  OUT  UINTN  *FlashSize,
+  OUT  UINTN  *BlockSize
+  );
+
+/**
+  Set AMD Capsule SMM Flag hook
+
+  @param[out] Reserved                    Not used; Must be 0.
+
+  @retval EFI_SUCCESS                     Set successfully.
+
+**/
+
+typedef EFI_STATUS (*AMD_CAPSULE_SMM_HOOK) (
+  IN       UINT32  Reserved
+  );
+
+typedef struct _AMD_CAPSULE_SMM_HOOK_PROTOCOL {
+  AMD_CAPSULE_SMM_HOOK    Hook;
+} AMD_CAPSULE_SMM_HOOK_PROTOCOL;
+
+extern EFI_GUID  gAmdSetCapsuleS3FlagGuid;
+extern EFI_GUID  gAmdCapsuleSmmHookProtocolGuid;
+
+#endif // _FLASH_UPDATE_SMM_H_
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.inf
new file mode 100644
index 0000000000..f39e814512
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmm.inf
@@ -0,0 +1,59 @@
+## @file
+#  Flash UpdateSmm
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FlashUpdateSmm
+  FILE_GUID                      = 42859181-A407-4CF2-A9A7-5848FEAA8958
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x0001000A
+  ENTRY_POINT                    = FlashUpdateServiceInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  FlashUpdateSmm.c
+  FlashUpdateSmm.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  AgesaPublic/AgesaPublic.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  SmmServicesTableLib
+  DebugLib
+  BaseLib
+  MemoryAllocationLib
+  SmmMemLib
+  PcdLib
+  IoLib
+
+[Protocols]
+  gEfiSmmSpiProtocolGuid                  ## CONSUME
+
+  gEfiSmmSpiFlashUpdateProtocolGuid       ## PRODUCE
+
+  gAmdCapsuleSmmHookProtocolGuid          ## CONSUME
+
+[Guids]
+  gAmdSetCapsuleS3FlagGuid
+
+[Pcd]
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress
+
+[Depex]
+  gEfiSmmSpiProtocolGuid
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.c
new file mode 100644
index 0000000000..80e60b30fd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.c
@@ -0,0 +1,407 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ ******************************************************************************
+ */
+
+#include "FlashUpdateCommon.h"
+
+EFI_EVENT                       mVirtualAddressChangeEvent = NULL;
+UINTN                           *mFlashSize                = NULL;
+UINTN                           *mBlockSize                = NULL;
+EFI_SMM_COMMUNICATION_PROTOCOL  *mSmmCommunication         = NULL;
+UINT8                           *mRweBuffer                = NULL;
+UINTN                           mRweBufferSize;
+
+EFI_SPI_FLASH_UPDATE_PROTOCOL  mEfiSpiFlashUpdateProtocol = {
+  SfuProtocolFlashFdRead,
+  SfuProtocolFlashFdErase,
+  SfuProtocolFlashFdWrite,
+  SfuProtocolGetFlashSizeBlockSize,
+};
+
+/**
+  Initialize the communicate buffer.
+
+  The communicate buffer is: SMM_COMMUNICATE_HEADER + SMM_COMM_RWE_FLASH + Payload.
+  The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_COMM_RWE_FLASH_SIZE + FlashSize.
+
+  @param[out]      DataPtr          Points to the data in the communicate buffer.
+
+**/
+VOID
+EFIAPI
+InitCommunicateBuffer (
+  OUT VOID  **DataPtr
+  )
+{
+  EFI_SMM_COMMUNICATE_HEADER  *SmmCommunicateHeader;
+
+  SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)mRweBuffer;
+  CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmSpiFlashUpdateProtocolGuid);
+  SmmCommunicateHeader->MessageLength = SMM_COMM_RWE_FLASH_SIZE;
+
+  *DataPtr = (SMM_COMM_RWE_FLASH *)((EFI_SMM_COMMUNICATE_HEADER *)mRweBuffer)->Data;
+}
+
+/**
+  Read data from flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[out] Buffer                      Buffer contain the read data.
+
+  @retval EFI_SUCCESS                     Read successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+SfuProtocolFlashFdRead (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes,
+  OUT VOID   *Buffer
+  )
+{
+  EFI_STATUS          Status;
+  SMM_COMM_RWE_FLASH  *RweFlashBuffer;
+
+  if ((FlashAddress >= *mFlashSize) || (NumBytes == 0) || (Buffer == NULL) ||
+      (FlashAddress + NumBytes > *mFlashSize))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RweFlashBuffer = NULL;
+
+  InitCommunicateBuffer ((VOID **)&RweFlashBuffer);
+
+  if (RweFlashBuffer == NULL) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  RweFlashBuffer->id           = SPI_SMM_COMM_ID_READ_FLASH;
+  RweFlashBuffer->FlashAddress = FlashAddress;
+  RweFlashBuffer->NumBytes     = NumBytes;
+  CopyMem (RweFlashBuffer->Buffer, Buffer, NumBytes);
+
+  //
+  // Send data to SMM.
+  //
+  Status = mSmmCommunication->Communicate (
+                                mSmmCommunication,
+                                mRweBuffer,
+                                &mRweBufferSize
+                                );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Get data from SMM
+  //
+  if (!EFI_ERROR (RweFlashBuffer->ReturnStatus)) {
+    CopyMem (Buffer, RweFlashBuffer->Buffer, NumBytes);
+  }
+
+  return RweFlashBuffer->ReturnStatus;
+}
+
+/**
+  Erase flash region according to input in a block size.
+
+  @param[in] FlashAddress                 Physical flash address.
+  @param[in] NumBytes                     Number in Byte, a block size in flash device.
+
+  @retval EFI_SUCCESS                     Erase successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+SfuProtocolFlashFdErase (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes
+  )
+{
+  EFI_STATUS          Status;
+  SMM_COMM_RWE_FLASH  *RweFlashBuffer;
+
+  if ((FlashAddress >= *mFlashSize) || (NumBytes == 0) || (NumBytes > *mFlashSize) ||
+      (FlashAddress + NumBytes > *mFlashSize))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RweFlashBuffer = NULL;
+
+  InitCommunicateBuffer ((VOID **)&RweFlashBuffer);
+
+  if (RweFlashBuffer == NULL) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  RweFlashBuffer->id           = SPI_SMM_COMM_ID_ERASE_FALSH;
+  RweFlashBuffer->FlashAddress = FlashAddress;
+  RweFlashBuffer->NumBytes     = NumBytes;
+
+  //
+  // Send data to SMM.
+  //
+  Status = mSmmCommunication->Communicate (
+                                mSmmCommunication,
+                                mRweBuffer,
+                                &mRweBufferSize
+                                );
+  ASSERT_EFI_ERROR (Status);
+
+  return RweFlashBuffer->ReturnStatus;
+}
+
+/**
+  Write data to flash device.
+
+  Write Buffer(FlashAddress|NumBytes) to flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[in]  Buffer                      Buffer contain the write data.
+
+  @retval EFI_SUCCESS                     Write successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+SfuProtocolFlashFdWrite (
+  IN  UINTN  FlashAddress,
+  IN  UINTN  NumBytes,
+  IN  UINT8  *Buffer
+  )
+{
+  EFI_STATUS          Status;
+  SMM_COMM_RWE_FLASH  *RweFlashBuffer;
+
+  if ((FlashAddress >= *mFlashSize) || (NumBytes == 0) || (NumBytes > *mFlashSize) || (Buffer == NULL) ||
+      (FlashAddress + NumBytes > *mFlashSize))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RweFlashBuffer = NULL;
+
+  InitCommunicateBuffer ((VOID **)&RweFlashBuffer);
+
+  if (RweFlashBuffer == NULL) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  RweFlashBuffer->id           = SPI_SMM_COMM_ID_WRITE_FALSH;
+  RweFlashBuffer->FlashAddress = FlashAddress;
+  RweFlashBuffer->NumBytes     = NumBytes;
+  CopyMem (RweFlashBuffer->Buffer, Buffer, NumBytes);
+
+  //
+  // Send data to SMM.
+  //
+  Status = mSmmCommunication->Communicate (
+                                mSmmCommunication,
+                                mRweBuffer,
+                                &mRweBufferSize
+                                );
+  ASSERT_EFI_ERROR (Status);
+
+  return RweFlashBuffer->ReturnStatus;
+}
+
+/**
+  Get flash device size and flash block size.
+
+  @param[out] FlashSize                   Pointer to the size of flash device.
+  @param[out] BlockSize                   Pointer to the size of block in flash device.
+
+  @retval EFI_SUCCESS                     Get successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+
+**/
+EFI_STATUS
+EFIAPI
+SfuProtocolGetFlashSizeBlockSize (
+  OUT  UINTN  *FlashSize,
+  OUT  UINTN  *BlockSize
+  )
+{
+  if ((FlashSize == NULL) || (BlockSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *FlashSize = *mFlashSize;
+  *BlockSize = *mBlockSize;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+
+  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+  It convers pointer to new virtual address.
+
+  @param[in]  Event        Event whose notification function is being invoked.
+  @param[in]  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+SpiFlashAddressChangeEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EfiConvertPointer (0x0, (VOID **)&mRweBuffer);
+  EfiConvertPointer (0x0, (VOID **)&mSmmCommunication);
+  EfiConvertPointer (0x0, (VOID **)&mBlockSize);
+  EfiConvertPointer (0x0, (VOID **)&mFlashSize);
+}
+
+/**
+  Get flash device size and flash block size from SMM.
+
+  @param[in] VOID
+
+  @retval EFI_SUCCESS                     Get successfully.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+EFIAPI
+GetFlashSizeBlockSize (
+  VOID
+  )
+{
+  EFI_STATUS                          Status;
+  UINTN                               CommSize;
+  UINT8                               *CommBuffer;
+  EFI_SMM_COMMUNICATE_HEADER          *SmmCommunicateHeader;
+  SMM_COMM_GET_FLASH_SIZE_BLOCK_SIZE  *SmmGetFlashSizeBlockSize;
+
+  CommBuffer               = NULL;
+  SmmCommunicateHeader     = NULL;
+  SmmGetFlashSizeBlockSize = NULL;
+
+  //
+  // Init the communicate buffer. The buffer size is:
+  // SMM_COMMUNICATE_HEADER_SIZE + sizeof (SMM_COMM_GET_FLASH_SIZE_BLOCK_SIZE)
+  //
+  CommSize   = SMM_COMMUNICATE_HEADER_SIZE + sizeof (SMM_COMM_GET_FLASH_SIZE_BLOCK_SIZE);
+  CommBuffer = AllocateRuntimePool (CommSize);
+  if (CommBuffer == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    return Status;
+  }
+
+  SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommBuffer;
+  CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmSpiFlashUpdateProtocolGuid);
+  SmmCommunicateHeader->MessageLength = sizeof (SMM_COMM_GET_FLASH_SIZE_BLOCK_SIZE);
+
+  SmmGetFlashSizeBlockSize     = (SMM_COMM_GET_FLASH_SIZE_BLOCK_SIZE *)SmmCommunicateHeader->Data;
+  SmmGetFlashSizeBlockSize->id = SPI_SMM_COMM_ID_GET_FLASH_SIZE_BLOCK_SIZE;
+
+  //
+  // Send data to SMM.
+  //
+  Status = mSmmCommunication->Communicate (mSmmCommunication, CommBuffer, &CommSize);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = SmmGetFlashSizeBlockSize->ReturnStatus;
+  if (EFI_ERROR (Status)) {
+    if (CommBuffer != NULL) {
+      FreePool (CommBuffer);
+    }
+
+    return Status;
+  }
+
+  //
+  // Get data from SMM.
+  //
+  *mFlashSize = SmmGetFlashSizeBlockSize->FlashSize;
+  *mBlockSize = SmmGetFlashSizeBlockSize->BlockSize;
+
+  if (CommBuffer != NULL) {
+    FreePool (CommBuffer);
+  }
+
+  return Status;
+}
+
+/**
+  Update Flash Driver main entry point.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       Update Flash service successfully initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+FlashUpdateSmmRuntimeInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HANDLE  Handle;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiSmmCommunicationProtocolGuid,
+                  NULL,
+                  (VOID **)&mSmmCommunication
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Allocate memory for flash device size communicate buffer.
+  //
+  mFlashSize = AllocateRuntimePool (sizeof (UINTN));
+  ASSERT (mFlashSize != NULL);
+
+  //
+  // Allocate memory for flash device block size communicate buffer.
+  //
+  mBlockSize = AllocateRuntimePool (sizeof (UINTN));
+  ASSERT (mBlockSize != NULL);
+
+  Status = GetFlashSizeBlockSize ();
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Allocate memory for update flash communicate buffer.
+  //
+  mRweBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_COMM_RWE_FLASH_SIZE + *mFlashSize;
+  mRweBuffer     = AllocateRuntimePool (mRweBufferSize);
+  ASSERT (mRweBuffer != NULL);
+
+  gBS->CreateEventEx (
+         EVT_NOTIFY_SIGNAL,
+         TPL_NOTIFY,
+         SpiFlashAddressChangeEvent,
+         NULL,
+         &gEfiEventVirtualAddressChangeGuid,
+         &mVirtualAddressChangeEvent
+         );
+
+  Handle = NULL;
+  Status = gBS->InstallProtocolInterface (
+                  &Handle,
+                  &gEfiSpiFlashUpdateProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mEfiSpiFlashUpdateProtocol
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.inf
new file mode 100644
index 0000000000..7f606dd048
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/FlashUpdateSmmRuntimeDxe.inf
@@ -0,0 +1,48 @@
+## @file
+#  Flash Update SmmRuntimeDxe
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FlashUpdateSmmRuntimeDxe
+  FILE_GUID                      = FA08552D-9666-42A0-A327-BF342B03DA2C
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = FlashUpdateSmmRuntimeInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  FlashUpdateSmmRuntimeDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  DebugLib
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  UefiRuntimeLib
+
+[Protocols]
+  gEfiSmmCommunicationProtocolGuid              ## CONSUME
+  gEfiSmmSpiFlashUpdateProtocolGuid             ## CONSUME
+  gEfiSpiFlashUpdateProtocolGuid                ## PRODUCE
+
+[Guids]
+  gEfiEventVirtualAddressChangeGuid             ## CONSUME ## Event
+
+[Depex]
+  gEfiSmmCommunicationProtocolGuid
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/PcRtc.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/PcRtc.h
new file mode 100644
index 0000000000..2354eaa2b7
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FlashUpdate/PcRtc.h
@@ -0,0 +1,375 @@
+/** @file
+  Implements AMD PcRtc
+  Header file for real time clock driver.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RTC_H_
+#define RTC_H_
+
+#include <Uefi.h>
+
+#include <Guid/Acpi.h>
+
+#include <Protocol/RealTimeClock.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+typedef struct {
+  EFI_LOCK    RtcLock;
+  INT16       SavedTimeZone;
+  UINT8       Daylight;
+  UINT8       CenturyRtcAddress;
+} PC_RTC_MODULE_GLOBALS;
+
+extern PC_RTC_MODULE_GLOBALS  mModuleGlobal;
+
+#define PCAT_RTC_ADDRESS_REGISTER  0x70
+#define PCAT_RTC_DATA_REGISTER     0x71
+
+//
+// Dallas DS12C887 Real Time Clock
+//
+#define RTC_ADDRESS_SECONDS           0   // R/W  Range 0..59
+#define RTC_ADDRESS_SECONDS_ALARM     1   // R/W  Range 0..59
+#define RTC_ADDRESS_MINUTES           2   // R/W  Range 0..59
+#define RTC_ADDRESS_MINUTES_ALARM     3   // R/W  Range 0..59
+#define RTC_ADDRESS_HOURS             4   // R/W  Range 1..12 or 0..23 Bit 7 is AM/PM
+#define RTC_ADDRESS_HOURS_ALARM       5   // R/W  Range 1..12 or 0..23 Bit 7 is AM/PM
+#define RTC_ADDRESS_DAY_OF_THE_WEEK   6   // R/W  Range 1..7
+#define RTC_ADDRESS_DAY_OF_THE_MONTH  7   // R/W  Range 1..31
+#define RTC_ADDRESS_MONTH             8   // R/W  Range 1..12
+#define RTC_ADDRESS_YEAR              9   // R/W  Range 0..99
+#define RTC_ADDRESS_REGISTER_A        10  // R/W[0..6]  R0[7]
+#define RTC_ADDRESS_REGISTER_B        11  // R/W
+#define RTC_ADDRESS_REGISTER_C        12  // RO
+#define RTC_ADDRESS_REGISTER_D        13  // RO
+//
+// Date and time initial values.
+// They are used if the RTC values are invalid during driver initialization
+//
+#define RTC_INIT_SECOND  0
+#define RTC_INIT_MINUTE  0
+#define RTC_INIT_HOUR    0
+#define RTC_INIT_DAY     1
+#define RTC_INIT_MONTH   1
+
+#pragma pack(1)
+//
+// Register A
+//
+typedef struct {
+  UINT8    Rs  : 4; // Rate Selection Bits
+  UINT8    Dv  : 3; // Divisor
+  UINT8    Uip : 1; // Update in progress
+} RTC_REGISTER_A_BITS;
+
+typedef union {
+  RTC_REGISTER_A_BITS    Bits;
+  UINT8                  Data;
+} RTC_REGISTER_A;
+
+//
+// Register B
+//
+typedef struct {
+  UINT8    Dse  : 1; // 0 - Daylight saving disabled  1 - Daylight savings enabled
+  UINT8    Mil  : 1; // 0 - 12 hour mode              1 - 24 hour mode
+  UINT8    Dm   : 1; // 0 - BCD Format                1 - Binary Format
+  UINT8    Sqwe : 1; // 0 - Disable SQWE output       1 - Enable SQWE output
+  UINT8    Uie  : 1; // 0 - Update INT disabled       1 - Update INT enabled
+  UINT8    Aie  : 1; // 0 - Alarm INT disabled        1 - Alarm INT Enabled
+  UINT8    Pie  : 1; // 0 - Periodic INT disabled     1 - Periodic INT Enabled
+  UINT8    Set  : 1; // 0 - Normal operation.         1 - Updates inhibited
+} RTC_REGISTER_B_BITS;
+
+typedef union {
+  RTC_REGISTER_B_BITS    Bits;
+  UINT8                  Data;
+} RTC_REGISTER_B;
+
+//
+// Register C
+//
+typedef struct {
+  UINT8    Reserved : 4; // Read as zero.  Can not be written.
+  UINT8    Uf       : 1; // Update End Interrupt Flag
+  UINT8    Af       : 1; // Alarm Interrupt Flag
+  UINT8    Pf       : 1; // Periodic Interrupt Flag
+  UINT8    Irqf     : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE
+} RTC_REGISTER_C_BITS;
+
+typedef union {
+  RTC_REGISTER_C_BITS    Bits;
+  UINT8                  Data;
+} RTC_REGISTER_C;
+
+//
+// Register D
+//
+typedef struct {
+  UINT8    Reserved : 7; // Read as zero.  Can not be written.
+  UINT8    Vrt      : 1; // Valid RAM and Time
+} RTC_REGISTER_D_BITS;
+
+typedef union {
+  RTC_REGISTER_D_BITS    Bits;
+  UINT8                  Data;
+} RTC_REGISTER_D;
+
+#pragma pack()
+
+/**
+  Initialize RTC.
+
+  @param  Global            For global use inside this module.
+
+  @retval EFI_DEVICE_ERROR  Initialization failed due to device error.
+  @retval EFI_SUCCESS       Initialization successful.
+
+**/
+EFI_STATUS
+PcRtcInit (
+  IN PC_RTC_MODULE_GLOBALS  *Global
+  );
+
+/**
+  Sets the current local time and date information.
+
+  @param  Time                  A pointer to the current time.
+  @param  Global                For global use inside this module.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER A time field is out of range.
+  @retval EFI_DEVICE_ERROR      The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+PcRtcSetTime (
+  IN EFI_TIME               *Time,
+  IN PC_RTC_MODULE_GLOBALS  *Global
+  );
+
+/**
+  Returns the current time and date information, and the time-keeping capabilities
+  of the hardware platform.
+
+  @param  Time          A pointer to storage to receive a snapshot of the current time.
+  @param  Capabilities  An optional pointer to a buffer to receive the real time clock
+                        device's capabilities.
+  @param  Global        For global use inside this module.
+
+  @retval EFI_SUCCESS            The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER  Time is NULL.
+  @retval EFI_DEVICE_ERROR       The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+PcRtcGetTime (
+  OUT EFI_TIME *Time,
+  OUT EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL
+  IN  PC_RTC_MODULE_GLOBALS *Global
+  );
+
+/**
+  Sets the system wakeup alarm clock time.
+
+  @param  Enabled  Enable or disable the wakeup alarm.
+  @param  Time     If Enable is TRUE, the time to set the wakeup alarm for.
+                   If Enable is FALSE, then this parameter is optional, and may be NULL.
+  @param  Global   For global use inside this module.
+
+  @retval EFI_SUCCESS           If Enable is TRUE, then the wakeup alarm was enabled.
+                                If Enable is FALSE, then the wakeup alarm was disabled.
+  @retval EFI_INVALID_PARAMETER A time field is out of range.
+  @retval EFI_DEVICE_ERROR      The wakeup time could not be set due to a hardware error.
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+PcRtcSetWakeupTime (
+  IN BOOLEAN Enable,
+  IN EFI_TIME *Time, OPTIONAL
+  IN PC_RTC_MODULE_GLOBALS  *Global
+  );
+
+/**
+  Returns the current wakeup alarm clock setting.
+
+  @param  Enabled  Indicates if the alarm is currently enabled or disabled.
+  @param  Pending  Indicates if the alarm signal is pending and requires acknowledgement.
+  @param  Time     The current alarm setting.
+  @param  Global   For global use inside this module.
+
+  @retval EFI_SUCCESS           The alarm settings were returned.
+  @retval EFI_INVALID_PARAMETER Enabled is NULL.
+  @retval EFI_INVALID_PARAMETER Pending is NULL.
+  @retval EFI_INVALID_PARAMETER Time is NULL.
+  @retval EFI_DEVICE_ERROR      The wakeup time could not be retrieved due to a hardware error.
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+PcRtcGetWakeupTime (
+  OUT BOOLEAN                *Enabled,
+  OUT BOOLEAN                *Pending,
+  OUT EFI_TIME               *Time,
+  IN  PC_RTC_MODULE_GLOBALS  *Global
+  );
+
+/**
+  The user Entry Point for PcRTC module.
+
+  This is the entrhy point for PcRTC module. It installs the UEFI runtime service
+  including GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().
+
+  @param  ImageHandle    The firmware allocated handle for the EFI image.
+  @param  SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS    The entry point is executed successfully.
+  @retval Others         Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePcRtc (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+/**
+  See if all fields of a variable of EFI_TIME type is correct.
+
+  @param   Time   The time to be checked.
+
+  @retval  EFI_INVALID_PARAMETER  Some fields of Time are not correct.
+  @retval  EFI_SUCCESS            Time is a valid EFI_TIME variable.
+
+**/
+EFI_STATUS
+RtcTimeFieldsValid (
+  IN EFI_TIME  *Time
+  );
+
+/**
+  Converts time from EFI_TIME format defined by UEFI spec to RTC's.
+
+  This function converts time from EFI_TIME format defined by UEFI spec to RTC's.
+  If data mode of RTC is BCD, then converts EFI_TIME to it.
+  If RTC is in 12-hour format, then converts EFI_TIME to it.
+
+  @param   Time       On input, the time data read from UEFI to convert
+                      On output, the time converted to RTC format
+  @param   RegisterB  Value of Register B of RTC, indicating data mode
+**/
+VOID
+ConvertEfiTimeToRtcTime (
+  IN OUT EFI_TIME        *Time,
+  IN     RTC_REGISTER_B  RegisterB
+  );
+
+/**
+  Converts time read from RTC to EFI_TIME format defined by UEFI spec.
+
+  This function converts raw time data read from RTC to the EFI_TIME format
+  defined by UEFI spec.
+  If data mode of RTC is BCD, then converts it to decimal,
+  If RTC is in 12-hour format, then converts it to 24-hour format.
+
+  @param   Time       On input, the time data read from RTC to convert
+                      On output, the time converted to UEFI format
+  @param   RegisterB  Value of Register B of RTC, indicating data mode
+                      and hour format.
+
+  @retval  EFI_INVALID_PARAMETER  Parameters passed in are invalid.
+  @retval  EFI_SUCCESS            Convert RTC time to EFI time successfully.
+
+**/
+EFI_STATUS
+ConvertRtcTimeToEfiTime (
+  IN OUT EFI_TIME        *Time,
+  IN     RTC_REGISTER_B  RegisterB
+  );
+
+/**
+  Wait for a period for the RTC to be ready.
+
+  @param    Timeout  Tell how long it should take to wait.
+
+  @retval   EFI_DEVICE_ERROR   RTC device error.
+  @retval   EFI_SUCCESS        RTC is updated and ready.
+**/
+EFI_STATUS
+RtcWaitToUpdate (
+  UINTN  Timeout
+  );
+
+/**
+  See if field Day of an EFI_TIME is correct.
+
+  @param    Time   Its Day field is to be checked.
+
+  @retval   TRUE   Day field of Time is correct.
+  @retval   FALSE  Day field of Time is NOT correct.
+**/
+BOOLEAN
+DayValid (
+  IN  EFI_TIME  *Time
+  );
+
+/**
+  Check if it is a leapyear.
+
+  @param    Time   The time to be checked.
+
+  @retval   TRUE   It is a leapyear.
+  @retval   FALSE  It is NOT a leapyear.
+**/
+BOOLEAN
+IsLeapYear (
+  IN EFI_TIME  *Time
+  );
+
+/**
+  Get the century RTC address from the ACPI FADT table.
+
+  @return  The century RTC address or 0 if not found.
+**/
+UINT8
+GetCenturyRtcAddress (
+  VOID
+  );
+
+/**
+  Notification function of ACPI Table change.
+
+  This is a notification function registered on ACPI Table change event.
+  It saves the Century address stored in ACPI FADT table.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+PcRtcAcpiTableChangeCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+#endif
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114586): https://edk2.groups.io/g/devel/message/114586
Mute This Topic: https://groups.io/mt/103975450/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 11/32] AMD/VanGoghBoard: Check in FvbServices
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (9 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 10/32] AMD/VanGoghBoard: Check in FlashUpdate Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 12/32] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib Zhai, MingXin (Duke) via groups.io
                   ` (21 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial FvbServices module. It describes platform flash IC information
  for FlashUpdate module to send command correctly.
  Different flash ICs may use the different Opcodes.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../VanGoghCommonPkg/FvbServices/FvbInfo.c    |  120 ++
 .../FvbServices/FwBlockService.c              | 1285 +++++++++++++++++
 .../FvbServices/FwBlockService.h              |  515 +++++++
 .../FvbServices/PlatformSmmSpi.inf            |   68 +
 4 files changed, 1988 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FvbInfo.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/PlatformSmmSpi.inf

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FvbInfo.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FvbInfo.c
new file mode 100644
index 0000000000..c0be635864
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FvbInfo.c
@@ -0,0 +1,120 @@
+/** @file
+Defines data structure that is the volume header found.These data is intent
+to decouple FVB driver with FV header.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013 Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiDxe.h>
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Guid/EventGroup.h>
+#include <Guid/FirmwareFileSystem2.h>
+#include <Guid/SystemNvDataGuid.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+#include <Protocol/DevicePath.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/UefiLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+#define FVB_MEDIA_BLOCK_SIZE  (0x00010000)
+
+#define SYSTEM_NV_BLOCK_NUM  ((FixedPcdGet32(PcdFlashNvStorageVariableSize)+ FixedPcdGet32(PcdFlashNvStorageFtwWorkingSize) + FixedPcdGet32(PcdFlashNvStorageFtwSpareSize))/ FVB_MEDIA_BLOCK_SIZE)
+
+typedef struct {
+  EFI_PHYSICAL_ADDRESS          BaseAddress;
+  EFI_FIRMWARE_VOLUME_HEADER    FvbInfo;
+  //
+  // EFI_FV_BLOCK_MAP_ENTRY    ExtraBlockMap[n];//n=0
+  //
+  EFI_FV_BLOCK_MAP_ENTRY        End[1];
+} EFI_FVB2_MEDIA_INFO;
+
+EFI_FVB2_MEDIA_INFO  mPlatformFvbMediaInfo =
+  //
+  // Systen NvStorage FVB
+  //
+{
+  0,
+  {
+    {
+      0,
+    },    // ZeroVector[16]
+    EFI_SYSTEM_NV_DATA_FV_GUID,
+    FVB_MEDIA_BLOCK_SIZE *SYSTEM_NV_BLOCK_NUM,
+    EFI_FVH_SIGNATURE,
+    EFI_FVB2_MEMORY_MAPPED |
+    EFI_FVB2_READ_ENABLED_CAP |
+    EFI_FVB2_READ_STATUS |
+    EFI_FVB2_WRITE_ENABLED_CAP |
+    EFI_FVB2_WRITE_STATUS |
+    EFI_FVB2_ERASE_POLARITY |
+    EFI_FVB2_ALIGNMENT_16,
+    sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY),
+    0xFBFF,    // CheckSum
+    0,         // ExtHeaderOffset
+    {
+      0,
+    },    // Reserved[1]
+    2,    // Revision
+    {
+      {
+        SYSTEM_NV_BLOCK_NUM,
+        FVB_MEDIA_BLOCK_SIZE,
+      }
+    }
+  },
+  {
+    {
+      0,
+      0
+    }
+  }
+};
+
+/**
+  Get Fvb information.
+
+  @param[in] BaseAddress    The base address compare with NvStorageVariable base address.
+  @param[out] FvbInfo        Fvb information.
+
+  @retval EFI_SUCCESS       Get Fvb information successfully.
+  @retval EFI_NOT_FOUND     Not find Fvb information.
+
+**/
+EFI_STATUS
+EFIAPI
+GetFvbInfo (
+  IN  UINT64                      BaseAddress,
+  OUT EFI_FIRMWARE_VOLUME_HEADER  **FvbInfo
+  )
+{
+  mPlatformFvbMediaInfo.BaseAddress = PcdGet32 (PcdFlashNvStorageVariableBase);
+
+  if (mPlatformFvbMediaInfo.BaseAddress == BaseAddress) {
+    *FvbInfo = &mPlatformFvbMediaInfo.FvbInfo;
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.c
new file mode 100644
index 0000000000..f514ad772a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.c
@@ -0,0 +1,1285 @@
+/** @file
+  Implements FvbServicesSmm
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013-2016 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifdef _MSC_VER
+  #pragma optimize( "", off )
+#endif
+
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC push_options
+    #pragma GCC optimize ("O0")
+  #else
+    #pragma clang optimize off
+  #endif
+#endif
+
+#include "FwBlockService.h"
+
+#define EFI_FVB2_STATUS  (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)
+
+ESAL_FWB_GLOBAL  *mFvbModuleGlobal;
+
+FV_MEMMAP_DEVICE_PATH  mFvMemmapDevicePathTemplate = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_MEMMAP_DP,
+      {
+        (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
+        (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)
+      }
+    },
+    EfiMemoryMappedIO,
+    (EFI_PHYSICAL_ADDRESS)0,
+    (EFI_PHYSICAL_ADDRESS)0,
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      END_DEVICE_PATH_LENGTH,
+      0
+    }
+  }
+};
+
+FV_PIWG_DEVICE_PATH  mFvPIWGDevicePathTemplate = {
+  {
+    {
+      MEDIA_DEVICE_PATH,
+      MEDIA_PIWG_FW_VOL_DP,
+      {
+        (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),
+        (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)
+      }
+    },
+    { 0 }
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      END_DEVICE_PATH_LENGTH,
+      0
+    }
+  }
+};
+
+EFI_FW_VOL_BLOCK_DEVICE  mFvbDeviceTemplate = {
+  FVB_DEVICE_SIGNATURE,
+  NULL,
+  0,
+  {
+    FvbProtocolGetAttributes,
+    FvbProtocolSetAttributes,
+    FvbProtocolGetPhysicalAddress,
+    FvbProtocolGetBlockSize,
+    FvbProtocolRead,
+    FvbProtocolWrite,
+    FvbProtocolEraseBlocks,
+    NULL
+  }
+};
+
+/**
+  Retrieves the physical address of a memory mapped FV
+
+  @param[in]  Instance    The FV instance whose base address is going to be returned.
+
+  @param[in]  Global      Pointer to ESAL_FWB_GLOBAL that contains all instance data.
+
+  @param[out] FwhInstance The EFI_FW_VOL_INSTANCE fimrware instance structure
+  @param[in]  Virtual     Whether CPU is in virtual or physical mode
+
+  @retval  EFI_SUCCESS            Successfully returns
+  @retval  EFI_INVALID_PARAMETER  Instance not found           -
+
+**/
+EFI_STATUS
+GetFvbInstance (
+  IN  UINTN                Instance,
+  IN  ESAL_FWB_GLOBAL      *Global,
+  OUT EFI_FW_VOL_INSTANCE  **FwhInstance,
+  IN BOOLEAN               Virtual
+  )
+{
+  EFI_FW_VOL_INSTANCE  *FwhRecord;
+
+  if (Instance >= Global->NumFv) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Find the right instance of the FVB private data
+  //
+  FwhRecord = Global->FvInstance[Virtual];
+  while (Instance > 0) {
+    FwhRecord = (EFI_FW_VOL_INSTANCE *)
+                (
+                 (UINTN)((UINT8 *)FwhRecord) + FwhRecord->VolumeHeader.HeaderLength +
+                 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
+                );
+    Instance--;
+  }
+
+  *FwhInstance = FwhRecord;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves the physical address of a memory mapped FV
+
+  @param[in]  Instance  The FV instance whose base address is going to be returned.
+
+  @param[out]  Address  Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
+                        that on successful return, contains the base address
+                        of the firmware volume.
+  @param[in]  Global    Pointer to ESAL_FWB_GLOBAL that contains all
+                        instance data
+  @param[in]  Virtual   Whether CPU is in virtual or physical mode
+
+  @retval  EFI_SUCCESS            Successfully returns
+  @retval  EFI_INVALID_PARAMETER  Instance not found            -
+   -
+
+**/
+EFI_STATUS
+FvbGetPhysicalAddress (
+  IN UINTN                  Instance,
+  OUT EFI_PHYSICAL_ADDRESS  *Address,
+  IN ESAL_FWB_GLOBAL        *Global,
+  IN BOOLEAN                Virtual
+  )
+{
+  EFI_FW_VOL_INSTANCE  *FwhInstance;
+  EFI_STATUS           Status;
+
+  FwhInstance = NULL;
+
+  //
+  // Find the right instance of the FVB private data
+  //
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+  ASSERT_EFI_ERROR (Status);
+  *Address = FwhInstance->FvBase[Virtual];
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves attributes, insures positive polarity of attribute bits, returns
+  resulting attributes in output parameter
+
+  @param[in]  Instance   The FV instance whose attributes is going to be
+                         returned
+  @param[out] Attributes Output buffer which contains attributes
+  @param[in]  Global     Pointer to ESAL_FWB_GLOBAL that contains all
+                         instance data
+  @param[in]  Virtual    Whether CPU is in virtual or physical mode
+
+  @retval    EFI_SUCCESS            Successfully returns
+  @retval    EFI_INVALID_PARAMETER  Instance not found
+
+**/
+EFI_STATUS
+FvbGetVolumeAttributes (
+  IN UINTN                  Instance,
+  OUT EFI_FVB_ATTRIBUTES_2  *Attributes,
+  IN ESAL_FWB_GLOBAL        *Global,
+  IN BOOLEAN                Virtual
+  )
+{
+  EFI_FW_VOL_INSTANCE  *FwhInstance;
+  EFI_STATUS           Status;
+
+  FwhInstance = NULL;
+
+  //
+  // Find the right instance of the FVB private data
+  //
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+  ASSERT_EFI_ERROR (Status);
+  *Attributes = FwhInstance->VolumeHeader.Attributes;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves the starting address of an LBA in an FV
+
+  @param[in]   Instance               The FV instance which the Lba belongs to
+  @param[in]   Lba                    The logical block address
+  @param[out]  LbaAddress             On output, contains the physical starting address
+                          of the Lba
+  @param[out]  LbaLength              On output, contains the length of the block
+  @param[out]  NumOfBlocks            A pointer to a caller allocated UINTN in which the
+                                      number of consecutive blocks starting with Lba is
+                                      returned. All blocks in this range have a size of
+                                      BlockSize
+  @param[in]  Global                  Pointer to ESAL_FWB_GLOBAL that contains all
+                                      instance data
+  @param[in]  Virtual                 Whether CPU is in virtual or physical mode
+  @retval  EFI_SUCCESS             Successfully returns
+  @retval  EFI_INVALID_PARAMETER   Instance not found
+
+**/
+EFI_STATUS
+FvbGetLbaAddress (
+  IN  UINTN            Instance,
+  IN  EFI_LBA          Lba,
+  OUT UINTN            *LbaAddress,
+  OUT UINTN            *LbaLength,
+  OUT UINTN            *NumOfBlocks,
+  IN  ESAL_FWB_GLOBAL  *Global,
+  IN  BOOLEAN          Virtual
+  )
+{
+  UINT32                  NumBlocks;
+  UINT32                  BlockLength;
+  UINTN                   Offset;
+  EFI_LBA                 StartLba;
+  EFI_LBA                 NextLba;
+  EFI_FW_VOL_INSTANCE     *FwhInstance;
+  EFI_FV_BLOCK_MAP_ENTRY  *BlockMap;
+  EFI_STATUS              Status;
+
+  FwhInstance = NULL;
+
+  //
+  // Find the right instance of the FVB private data
+  //
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+  ASSERT_EFI_ERROR (Status);
+
+  StartLba = 0;
+  Offset   = 0;
+  BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]);
+
+  //
+  // Parse the blockmap of the FV to find which map entry the Lba belongs to
+  //
+  while (TRUE) {
+    NumBlocks   = BlockMap->NumBlocks;
+    BlockLength = BlockMap->Length;
+
+    if ((NumBlocks == 0) || (BlockLength == 0)) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    NextLba = StartLba + NumBlocks;
+
+    //
+    // The map entry found
+    //
+    if ((Lba >= StartLba) && (Lba < NextLba)) {
+      Offset = Offset + (UINTN)MultU64x32 ((Lba - StartLba), BlockLength);
+      if (LbaAddress) {
+        *LbaAddress = FwhInstance->FvBase[Virtual] + Offset;
+      }
+
+      if (LbaLength) {
+        *LbaLength = BlockLength;
+      }
+
+      if (NumOfBlocks) {
+        *NumOfBlocks = (UINTN)(NextLba - Lba);
+      }
+
+      return EFI_SUCCESS;
+    }
+
+    StartLba = NextLba;
+    Offset   = Offset + NumBlocks * BlockLength;
+    BlockMap++;
+  }
+}
+
+/**
+  Reads specified number of bytes into a buffer from the specified block
+
+  @param[in]       Instance      The FV instance to be read from
+  @param[in]       Lba           The logical block address to be read from
+  @param[in]       BlockOffset   Offset into the block at which to begin reading
+  @param[in, out]  NumBytes      Pointer that on input contains the total size of
+                                 the buffer. On output, it contains the total number
+                                 of bytes read
+  @param[in]       Buffer        Pointer to a caller allocated buffer that will be
+                                 used to hold the data read
+  @param[in]       Global        Pointer to ESAL_FWB_GLOBAL that contains all
+                                 instance data
+  @param[in]       Virtual       Whether CPU is in virtual or physical mode
+
+  @retval   EFI_SUCCESS            The firmware volume was read successfully and
+                                   contents are in Buffer
+  @retval   EFI_BAD_BUFFER_SIZE    Read attempted across a LBA boundary. On output,
+                                   NumBytes contains the total number of bytes returned
+                                   in Buffer
+  @retval   EFI_ACCESS_DENIED      The firmware volume is in the ReadDisabled state
+  @retval   EFI_DEVICE_ERROR       The block device is not functioning correctly and
+                                   could not be read
+  @retval   EFI_INVALID_PARAMETER  Instance not found, or NumBytes, Buffer are NULL
+
+**/
+EFI_STATUS
+FvbReadBlock (
+  IN UINTN            Instance,
+  IN EFI_LBA          Lba,
+  IN UINTN            BlockOffset,
+  IN OUT UINTN        *NumBytes,
+  IN UINT8            *Buffer,
+  IN ESAL_FWB_GLOBAL  *Global,
+  IN BOOLEAN          Virtual
+  )
+
+{
+  EFI_FVB_ATTRIBUTES_2  Attributes;
+  UINTN                 LbaAddress;
+  UINTN                 LbaLength;
+  EFI_STATUS            Status;
+
+  DEBUG ((DEBUG_INFO, "Smm %a() enter\n", __FUNCTION__));
+
+  //
+  // Check for invalid conditions
+  //
+  if ((NumBytes == NULL) || (Buffer == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*NumBytes == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Check if the FV is read enabled
+  //
+  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
+
+  if ((Attributes & EFI_FVB2_READ_STATUS) == 0) {
+    return EFI_ACCESS_DENIED;
+  }
+
+  //
+  // Perform boundary checks and adjust NumBytes
+  //
+  if (BlockOffset > LbaLength) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (LbaLength < (*NumBytes + BlockOffset)) {
+    *NumBytes = (UINT32)(LbaLength - BlockOffset);
+    Status    = EFI_BAD_BUFFER_SIZE;
+  }
+
+  // DEBUG ((DEBUG_INFO, "ReadAddress: 0x%x, NumBytes: 0x%x\n", (UINT8 *) (LbaAddress + BlockOffset), *NumBytes));
+  CopyMem (Buffer, (UINT8 *)(LbaAddress + BlockOffset), (UINTN)(*NumBytes));
+
+  return Status;
+}
+
+/**
+  Writes specified number of bytes from the input buffer to the block
+
+  @param[in]       Instance      The FV instance to be written to
+  @param[in]       Lba           The starting logical block index to write to
+  @param[in]       BlockOffset   Offset into the block at which to begin writing
+  @param[in, out]  NumBytes      Pointer that on input contains the total size of
+                                 the buffer. On output, it contains the total number
+                                 of bytes actually written
+  @param[in]       Buffer        Pointer to a caller allocated buffer that contains
+                                 the source for the write
+  @param[in]       Global        Pointer to ESAL_FWB_GLOBAL that contains all
+                                 instance data
+  @param[in]       Virtual       Whether CPU is in virtual or physical mode
+
+  @retval  EFI_SUCCESS             The firmware volume was written successfully
+  @retval  EFI_BAD_BUFFER_SIZE     Write attempted across a LBA boundary. On output,
+                                   NumBytes contains the total number of bytes
+                                   actually written
+  @retval  EFI_ACCESS_DENIED       The firmware volume is in the WriteDisabled state
+  @retval  EFI_DEVICE_ERROR        The block device is not functioning correctly and
+                                   could not be written
+  @retval  EFI_INVALID_PARAMETER   Instance not found, or NumBytes, Buffer are NULL
+
+**/
+EFI_STATUS
+FvbWriteBlock (
+  IN UINTN            Instance,
+  IN EFI_LBA          Lba,
+  IN UINTN            BlockOffset,
+  IN OUT UINTN        *NumBytes,
+  IN UINT8            *Buffer,
+  IN ESAL_FWB_GLOBAL  *Global,
+  IN BOOLEAN          Virtual
+  )
+{
+  EFI_FVB_ATTRIBUTES_2  Attributes;
+  UINTN                 LbaAddress;
+  UINTN                 LbaLength;
+  EFI_STATUS            Status;
+
+  //
+  // Check for invalid conditions
+  //
+  if ((NumBytes == NULL) || (Buffer == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*NumBytes == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Check if the FV is write enabled
+  //
+  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
+
+  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
+    return EFI_ACCESS_DENIED;
+  }
+
+  //
+  // Perform boundary checks and adjust NumBytes
+  //
+  if (BlockOffset > LbaLength) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (LbaLength < (*NumBytes + BlockOffset)) {
+    *NumBytes = (UINT32)(LbaLength - BlockOffset);
+    Status    = EFI_BAD_BUFFER_SIZE;
+  }
+
+  //
+  // Write data
+  //
+  Status = FlashFdWrite (
+             LbaAddress + BlockOffset,
+             LbaAddress,
+             NumBytes,
+             Buffer,
+             LbaLength
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return Status;
+}
+
+/**
+  Erases and initializes a firmware volume block
+
+  @param[in]  Instance    The FV instance to be erased
+  @param[in]  Lba         The logical block index to be erased
+  @param[in]  Global      Pointer to ESAL_FWB_GLOBAL that contains all
+                          instance data
+  @param[in]  Virtual     Whether CPU is in virtual or physical mode
+
+  @retval  EFI_SUCCESS             The erase request was successfully completed
+  @retval  EFI_ACCESS_DENIED       The firmware volume is in the WriteDisabled state
+  @retval  EFI_DEVICE_ERROR        The block device is not functioning correctly and
+                                   could not be written. Firmware device may have been
+                                   partially erased
+  @retval  EFI_INVALID_PARAMETER   Instance not found
+
+**/
+EFI_STATUS
+FvbEraseBlock (
+  IN UINTN            Instance,
+  IN EFI_LBA          Lba,
+  IN ESAL_FWB_GLOBAL  *Global,
+  IN BOOLEAN          Virtual
+  )
+{
+  EFI_FVB_ATTRIBUTES_2  Attributes;
+  UINTN                 LbaAddress;
+  UINTN                 LbaLength;
+  EFI_STATUS            Status;
+
+  //
+  // Check if the FV is write enabled
+  //
+  FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
+
+  if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
+    return EFI_ACCESS_DENIED;
+  }
+
+  //
+  // Get the starting address of the block for erase.
+  //
+  Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = FlashFdErase (LbaAddress, LbaLength);
+
+  return Status;
+}
+
+/**
+  Modifies the current settings of the firmware volume according to the
+  input parameter, and returns the new setting of the volume
+
+  @param[in]       Instance          The FV instance whose attributes is going to be
+                                     modified
+  @param[in, out]  Attributes        On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
+                                     containing the desired firmware volume settings.
+                                     On successful return, it contains the new settings
+                                     of the firmware volume
+  @param[in]       Global            Pointer to ESAL_FWB_GLOBAL that contains all
+                                     instance data
+  @param[in]       Virtual           Whether CPU is in virtual or physical mode
+
+  @retval  EFI_SUCCESS             Successfully returns
+  @retval  EFI_ACCESS_DENIED       The volume setting is locked and cannot be modified
+  @retval  EFI_INVALID_PARAMETER   Instance not found, or The attributes requested are
+                                   in conflict with the capabilities as declared in the
+                                   firmware volume header
+
+**/
+EFI_STATUS
+FvbSetVolumeAttributes (
+  IN UINTN                     Instance,
+  IN OUT EFI_FVB_ATTRIBUTES_2  *Attributes,
+  IN ESAL_FWB_GLOBAL           *Global,
+  IN BOOLEAN                   Virtual
+  )
+{
+  EFI_FW_VOL_INSTANCE   *FwhInstance;
+  EFI_FVB_ATTRIBUTES_2  OldAttributes;
+  EFI_FVB_ATTRIBUTES_2  *AttribPtr;
+  UINT32                Capabilities;
+  UINT32                OldStatus;
+  UINT32                NewStatus;
+  EFI_STATUS            Status;
+  EFI_FVB_ATTRIBUTES_2  UnchangedAttributes;
+
+  FwhInstance = NULL;
+  //
+  // Find the right instance of the FVB private data
+  //
+  Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
+  ASSERT_EFI_ERROR (Status);
+
+  AttribPtr     = (EFI_FVB_ATTRIBUTES_2 *)&(FwhInstance->VolumeHeader.Attributes);
+  OldAttributes = *AttribPtr;
+  Capabilities  = OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \
+                                   EFI_FVB2_READ_ENABLED_CAP | \
+                                   EFI_FVB2_WRITE_DISABLED_CAP | \
+                                   EFI_FVB2_WRITE_ENABLED_CAP | \
+                                   EFI_FVB2_LOCK_CAP \
+                                   );
+  OldStatus = OldAttributes & EFI_FVB2_STATUS;
+  NewStatus = *Attributes & EFI_FVB2_STATUS;
+
+  UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP  | \
+                        EFI_FVB2_READ_ENABLED_CAP   | \
+                        EFI_FVB2_WRITE_DISABLED_CAP | \
+                        EFI_FVB2_WRITE_ENABLED_CAP  | \
+                        EFI_FVB2_LOCK_CAP           | \
+                        EFI_FVB2_STICKY_WRITE       | \
+                        EFI_FVB2_MEMORY_MAPPED      | \
+                        EFI_FVB2_ERASE_POLARITY     | \
+                        EFI_FVB2_READ_LOCK_CAP      | \
+                        EFI_FVB2_WRITE_LOCK_CAP     | \
+                        EFI_FVB2_ALIGNMENT;
+
+  //
+  // Some attributes of FV is read only can *not* be set
+  //
+  if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // If firmware volume is locked, no status bit can be updated
+  //
+  if (OldAttributes & EFI_FVB2_LOCK_STATUS) {
+    if (OldStatus ^ NewStatus) {
+      return EFI_ACCESS_DENIED;
+    }
+  }
+
+  //
+  // Test read disable
+  //
+  if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {
+    if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  // Test read enable
+  //
+  if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {
+    if (NewStatus & EFI_FVB2_READ_STATUS) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  // Test write disable
+  //
+  if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {
+    if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  // Test write enable
+  //
+  if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {
+    if (NewStatus & EFI_FVB2_WRITE_STATUS) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  // Test lock
+  //
+  if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {
+    if (NewStatus & EFI_FVB2_LOCK_STATUS) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  *AttribPtr  = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));
+  *AttribPtr  = (*AttribPtr) | NewStatus;
+  *Attributes = *AttribPtr;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves the physical address of the device.
+
+  @param[in]   This        Calling context
+  @param[out]  Address     Output buffer containing the address.
+
+  @retval EFI_SUCCESS  Successfully returns
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetPhysicalAddress (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  OUT EFI_PHYSICAL_ADDRESS                     *Address
+  )
+{
+  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
+
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);
+  return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, FALSE); // Hard coded to FALSE for SMM driver.
+}
+
+/**
+  Retrieve the size of a logical block
+
+  @param[in]   This           alling context
+  @param[in]   Lba            Indicates which block to return the size for.
+  @param[out]  BlockSize      A pointer to a caller allocated UINTN in which
+                              the size of the block is returned
+  @param[out]  NumOfBlocks    a pointer to a caller allocated UINTN in which the
+                              number of consecutive blocks starting with Lba is
+                              returned. All blocks in this range have a size of
+                              BlockSize
+
+  @retval  EFI_SUCCESS        The firmware volume was read successfully and
+                              contents are in Buffer
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetBlockSize (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  IN CONST EFI_LBA                             Lba,
+  OUT UINTN                                    *BlockSize,
+  OUT UINTN                                    *NumOfBlocks
+  )
+
+{
+  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
+
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+  return FvbGetLbaAddress (
+           FvbDevice->Instance,
+           Lba,
+           NULL,
+           BlockSize,
+           NumOfBlocks,
+           mFvbModuleGlobal,
+                 // EfiGoneVirtual ()
+           FALSE // Hard coded to FALSE for SMM driver.
+           );
+}
+
+/**
+    Retrieves Volume attributes.  No polarity translations are done.
+
+  @param[in]     This                 Calling context
+  @param[out]    Attributes           output buffer which contains attributes
+
+  @retval  EFI_SUCCESS            Successfully returns
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetAttributes (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  OUT EFI_FVB_ATTRIBUTES_2                     *Attributes
+  )
+
+{
+  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
+
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);
+  return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, FALSE); // Hard coded to FALSE for SMM driver.
+}
+
+/**
+  Sets Volume attributes. No polarity translations are done.
+
+  @param[in]   This                   Calling context
+  @param[out]  Attributes             output buffer which contains attributes
+
+  @retval  EFI_SUCCESS                Successfully returns
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolSetAttributes (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  IN OUT EFI_FVB_ATTRIBUTES_2                  *Attributes
+  )
+{
+  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
+
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+  // return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());
+  return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, FALSE); // Hard coded to FALSE for SMM driver.
+}
+
+/**
+  The EraseBlock() function erases one or more blocks as denoted by the
+  variable argument list. The entire parameter list of blocks must be verified
+  prior to erasing any blocks.  If a block is requested that does not exist
+  within the associated firmware volume (it has a larger index than the last
+  block of the firmware volume), the EraseBlock() function must return
+  EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
+
+  @param[in]  This                    Calling context
+  @param[in]  ...                     Starting LBA followed by Number of Lba to erase.
+                                      a -1 to terminate the list.
+
+  @retval  EFI_SUCCESS             The erase request was successfully completed
+  @retval  EFI_ACCESS_DENIED       The firmware volume is in the WriteDisabled state
+  @retval  EFI_DEVICE_ERROR        The block device is not functioning correctly and
+                                   could not be written. Firmware device may have been
+                                   partially erased.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolEraseBlocks (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  ...
+  )
+{
+  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
+  EFI_FW_VOL_INSTANCE      *FwhInstance;
+  UINTN                    NumOfBlocks;
+  VA_LIST                  args;
+  EFI_LBA                  StartingLba;
+  UINTN                    NumOfLba;
+  EFI_STATUS               Status;
+
+  FwhInstance = NULL;
+  FvbDevice   = FVB_DEVICE_FROM_THIS (This);
+
+  // Status    = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ());
+  Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, FALSE);    // Hard coded to FALSE for SMM driver.
+  ASSERT_EFI_ERROR (Status);
+
+  NumOfBlocks = FwhInstance->NumOfBlocks;
+
+  VA_START (args, This);
+
+  do {
+    StartingLba = VA_ARG (args, EFI_LBA);
+    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+      break;
+    }
+
+    NumOfLba = VA_ARG (args, UINTN);
+
+    //
+    // Check input parameters
+    //
+    if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) {
+      VA_END (args);
+      return EFI_INVALID_PARAMETER;
+    }
+  } while (TRUE);
+
+  VA_END (args);
+
+  VA_START (args, This);
+  do {
+    StartingLba = VA_ARG (args, EFI_LBA);
+    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+      break;
+    }
+
+    NumOfLba = VA_ARG (args, UINTN);
+
+    while (NumOfLba > 0) {
+      // Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ());
+      Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, FALSE); // Hard coded to FALSE for SMM driver.
+      if (EFI_ERROR (Status)) {
+        VA_END (args);
+        return Status;
+      }
+
+      StartingLba++;
+      NumOfLba--;
+    }
+  } while (TRUE);
+
+  VA_END (args);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Writes data beginning at Lba:Offset from FV. The write terminates either
+  when *NumBytes of data have been written, or when a block boundary is
+  reached.  *NumBytes is updated to reflect the actual number of bytes
+  written. The write opertion does not include erase. This routine will
+  attempt to write only the specified bytes. If the writes do not stick,
+  it will return an error.
+
+  @param[in]       This                   Calling context
+  @param[in]       Lba                    Block in which to begin write
+  @param[in]       Offset                 Offset in the block at which to begin write
+  @param[in, out]  NumBytes               On input, indicates the requested write size. On
+                                          output, indicates the actual number of bytes written
+  @param[in]       Buffer                 Buffer containing source data for the write.
+
+  @retval  EFI_SUCCESS            The firmware volume was written successfully
+  @retval  EFI_BAD_BUFFER_SIZE    Write attempted across a LBA boundary. On output,
+                                  NumBytes contains the total number of bytes
+                                  actually written
+  @retval  EFI_ACCESS_DENIED      The firmware volume is in the WriteDisabled state
+  @retval  EFI_DEVICE_ERROR       The block device is not functioning correctly and
+                                  could not be written
+  @retval  EFI_INVALID_PARAMETER  NumBytes or Buffer are NULL
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolWrite (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  IN       EFI_LBA                             Lba,
+  IN       UINTN                               Offset,
+  IN OUT   UINTN                               *NumBytes,
+  IN       UINT8                               *Buffer
+  )
+{
+  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
+
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+  return FvbWriteBlock (FvbDevice->Instance, (EFI_LBA)Lba, (UINTN)Offset, NumBytes, (UINT8 *)Buffer, mFvbModuleGlobal, FALSE); // Hard coded to FALSE for SMM driver.
+}
+
+/**
+  Reads data beginning at Lba:Offset from FV. The Read terminates either
+  when *NumBytes of data have been read, or when a block boundary is
+  reached.  *NumBytes is updated to reflect the actual number of bytes
+  written. The write opertion does not include erase. This routine will
+  attempt to write only the specified bytes. If the writes do not stick,
+  it will return an error.
+
+  @param[in]   This       Calling context
+  @param[in]   Lba        Block in which to begin Read
+  @param[in]   Offset     Offset in the block at which to begin Read
+  @param[out]  NumBytes   On input, indicates the requested write size. On
+                          output, indicates the actual number of bytes Read
+  @param[in]  Buffer      Buffer containing source data for the Read.
+
+  @retval  EFI_SUCCESS             The firmware volume was read successfully and
+                                   contents are in Buffer
+  @retval  EFI_BAD_BUFFER_SIZE     Read attempted across a LBA boundary. On output,
+                                   NumBytes contains the total number of bytes returned
+                                   in Buffer
+  @retval  EFI_ACCESS_DENIED       The firmware volume is in the ReadDisabled state
+  @retval  EFI_DEVICE_ERROR        The block device is not functioning correctly and
+                                   could not be read
+  @retval  EFI_INVALID_PARAMETER   NumBytes or Buffer are NULL
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolRead (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  IN CONST EFI_LBA                             Lba,
+  IN CONST UINTN                               Offset,
+  IN OUT UINTN                                 *NumBytes,
+  IN UINT8                                     *Buffer
+  )
+{
+  EFI_FW_VOL_BLOCK_DEVICE  *FvbDevice;
+
+  FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+  // return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());
+  return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, FALSE); // Hard coded to FALSE for SMM driver.
+}
+
+/**
+  Check the integrity of firmware volume header
+
+  @param[in]  FwVolHeader            A pointer to a firmware volume header
+
+  @retval  EFI_SUCCESS            The firmware volume is consistent
+  @retval  EFI_NOT_FOUND          The firmware volume has corrupted. So it is not an FV
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+  EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader
+  )
+{
+  //
+  // Verify the header revision, header signature, length
+  // Length of FvBlock cannot be 2**64-1
+  // HeaderLength cannot be an odd number
+  //
+  if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
+      (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
+      (FwVolHeader->FvLength == ((UINTN)-1)) ||
+      ((FwVolHeader->HeaderLength & 0x01) != 0)
+      )
+  {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Verify the header checksum
+  //
+  if (CalculateCheckSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength) != 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  This function does common initialization for FVB services
+
+  @param[in]  ImageHandle            A pointer to a image volume header
+  @param[in]  SystemTable            Pointer to the System Table
+
+  @retval  EFI_SUCCESS               initialization for FVB services successfully
+
+**/
+EFI_STATUS
+EFIAPI
+FvbInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_FW_VOL_INSTANCE              *FwhInstance;
+  EFI_FIRMWARE_VOLUME_HEADER       *FwVolHeader;
+  EFI_DXE_SERVICES                 *DxeServices;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  Descriptor;
+  UINT32                           BufferSize;
+  EFI_FV_BLOCK_MAP_ENTRY           *PtrBlockMapEntry;
+  EFI_HANDLE                       FwbHandle;
+  EFI_FW_VOL_BLOCK_DEVICE          *FvbDevice;
+  UINT32                           MaxLbaSize;
+  EFI_PHYSICAL_ADDRESS             BaseAddress;
+  UINTN                            NumOfBlocks;
+  UINT32                           PlatformFvBaseAddress;
+
+  //
+  // Get the DXE services table
+  //
+  DxeServices = gDS;
+
+  //
+  // Allocate runtime services data for global variable, which contains
+  // the private data of all firmware volume block instances
+  //
+  mFvbModuleGlobal = AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL));
+  ASSERT (mFvbModuleGlobal);
+
+  Status = gSmst->SmmLocateProtocol (&gEfiSmmSpiProtocolGuid, NULL, (VOID **)&mFvbModuleGlobal->SpiProtocol);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Calculate the total size for all firmware volume block instances
+  //
+  BufferSize            = 0;
+  PlatformFvBaseAddress = PcdGet32 (PcdFlashNvStorageVariableBase);
+  FwVolHeader           = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PlatformFvBaseAddress;
+  BufferSize           += (FwVolHeader->HeaderLength +
+                           sizeof (EFI_FW_VOL_INSTANCE) -
+                           sizeof (EFI_FIRMWARE_VOLUME_HEADER)
+                           );
+
+  //
+  // Only need to allocate once. There is only one copy of physical memory for
+  // the private data of each FV instance. But in virtual mode or in physical
+  // mode, the address of the the physical memory may be different.
+  //
+  mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] = AllocateRuntimePool (BufferSize);
+  ASSERT (mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] != NULL);
+
+  //
+  // Make a virtual copy of the FvInstance pointer.
+  //
+  FwhInstance                               = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];
+  mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance;
+
+  mFvbModuleGlobal->NumFv = 0;
+  MaxLbaSize              = 0;
+
+  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PlatformFvBaseAddress;
+  BaseAddress = (UINTN)FwVolHeader;
+
+  //
+  // Check if it is a "real" flash
+  //
+  Status = DxeServices->GetMemorySpaceDescriptor (
+                          BaseAddress,
+                          &Descriptor
+                          );
+  if (EFI_ERROR (Status)) {
+    return EFI_SUCCESS;
+  }
+
+  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
+  Status      = ValidateFvHeader (FwVolHeader);
+  if (EFI_ERROR (Status)) {
+    //
+    // Get FvbInfo to provide in FwhInstance.
+    //
+    Status = GetFvbInfo (BaseAddress, &FwVolHeader);
+    //
+    //  Write healthy FV header back.
+    //
+    CopyMem (
+      (VOID *)(UINTN)BaseAddress,
+      (VOID *)FwVolHeader,
+      FwVolHeader->HeaderLength
+      );
+  }
+
+  FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN)BaseAddress;
+  FwhInstance->FvBase[FVB_VIRTUAL]  = (UINTN)BaseAddress;
+
+  CopyMem ((UINTN *)&(FwhInstance->VolumeHeader), (UINTN *)FwVolHeader, FwVolHeader->HeaderLength);
+  FwVolHeader = &(FwhInstance->VolumeHeader);
+  EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL);
+
+  NumOfBlocks = 0;
+
+  for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
+    //
+    // Get the maximum size of a block.
+    //
+    if (MaxLbaSize < PtrBlockMapEntry->Length) {
+      MaxLbaSize = PtrBlockMapEntry->Length;
+    }
+
+    NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks;
+  }
+
+  //
+  // The total number of blocks in the FV.
+  //
+  FwhInstance->NumOfBlocks = NumOfBlocks;
+
+  //
+  // Add a FVB Protocol Instance
+  //
+  FvbDevice = AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE));
+  ASSERT (FvbDevice != NULL);
+
+  CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));
+
+  FvbDevice->Instance = mFvbModuleGlobal->NumFv;
+  mFvbModuleGlobal->NumFv++;
+
+  //
+  // Set up the devicepath
+  //
+  if (FwVolHeader->ExtHeaderOffset == 0) {
+    //
+    // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
+    //
+    FvbDevice->DevicePath                                                           = (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate);
+    ((FV_MEMMAP_DEVICE_PATH *)FvbDevice->DevicePath)->MemMapDevPath.StartingAddress = BaseAddress;
+    ((FV_MEMMAP_DEVICE_PATH *)FvbDevice->DevicePath)->MemMapDevPath.EndingAddress   = BaseAddress + FwVolHeader->FvLength - 1;
+  } else {
+    FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate);
+    CopyGuid (
+      &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName,
+      (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset)
+      );
+  }
+
+  FwbHandle = NULL;
+  Status    = gSmst->SmmInstallProtocolInterface (
+                       &FwbHandle,
+                       &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+                       EFI_NATIVE_INTERFACE,
+                       &FvbDevice->FwVolBlockInstance
+                       );
+  ASSERT_EFI_ERROR (Status);
+  FwhInstance = (EFI_FW_VOL_INSTANCE *)
+                (
+                 (UINTN)((UINT8 *)FwhInstance) + FwVolHeader->HeaderLength +
+                 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
+                );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Writes specified number of bytes from the input buffer to the address
+
+  @param[in]       WriteAddress      The FV address to be written to
+  @param[in]       Address           The FV address to be written to
+  @param[in, out]  NumBytes          Pointer that on input contains the total size of
+                                     the buffer. On output, it contains the total number
+                                     of bytes actually written
+  @param[in]       Buffer            Pointer to a caller allocated buffer that contains
+                                     the source for the write
+  @param[in]       LbaLength         contains the length of the Buffer.
+
+  @return The status returned from SpiProtocol().
+
+**/
+EFI_STATUS
+FlashFdWrite (
+  IN  UINTN     WriteAddress,
+  IN  UINTN     Address,
+  IN OUT UINTN  *NumBytes,
+  IN  UINT8     *Buffer,
+  IN  UINTN     LbaLength
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // TODO:  Suggested that this code be "critical section"
+  //
+  WriteAddress -= (PcdGet32 (PcdFlashAreaBaseAddress));
+  Status        = mFvbModuleGlobal->SpiProtocol->Execute (
+                                                   mFvbModuleGlobal->SpiProtocol,
+                                                   SPI_OPCODE_WRITE_INDEX, // OpcodeIndex
+                                                   0,                      // PrefixOpcodeIndex
+                                                   TRUE,                   // DataCycle
+                                                   TRUE,                   // Atomic
+                                                   TRUE,                   // ShiftOut
+                                                   WriteAddress,           // Address
+                                                   (UINT32)(*NumBytes),    // Data Number
+                                                   Buffer,
+                                                   EnumSpiRegionBios
+                                                   );
+
+  AsmWbinvd ();
+
+  return Status;
+}
+
+/**
+  Erase specified FV address
+
+  @param[in]       WriteAddress      The FV address to be written to
+  @param[in]       LbaLength         contains the length of the Buffer.
+
+  @return The status returned from SpiProtocol().
+
+**/
+EFI_STATUS
+FlashFdErase (
+  IN UINTN  WriteAddress,
+  IN UINTN  LbaLength
+  )
+{
+  EFI_STATUS    Status;
+  SPI_INSTANCE  *SpiInstance;
+
+  Status        = EFI_SUCCESS;
+  SpiInstance   = SPI_INSTANCE_FROM_SPIPROTOCOL (mFvbModuleGlobal->SpiProtocol);
+  WriteAddress -= (PcdGet32 (PcdFlashAreaBaseAddress));
+  while ((INTN)LbaLength > 0) {
+    if ((WriteAddress >= 0) && (WriteAddress + LbaLength <= SpiInstance->SpiInitTable.BiosSize)) {
+      Status = mFvbModuleGlobal->SpiProtocol->Execute (
+                                                mFvbModuleGlobal->SpiProtocol,
+                                                SPI_OPCODE_ERASE_INDEX, // OpcodeIndex
+                                                0,                      // PrefixOpcodeIndex
+                                                FALSE,                  // DataCycle
+                                                TRUE,                   // Atomic
+                                                TRUE,                   // ShiftOut
+                                                WriteAddress,           // Address
+                                                0,                      // Data Number
+                                                NULL,
+                                                EnumSpiRegionBios     // SPI_REGION_TYPE
+                                                );
+
+      if (Status != EFI_SUCCESS) {
+        return Status;
+      }
+    }
+
+    WriteAddress += SpiInstance->SpiInitTable.OpcodeMenu[SPI_OPCODE_ERASE_INDEX].Operation;
+    LbaLength    -= SpiInstance->SpiInitTable.OpcodeMenu[SPI_OPCODE_ERASE_INDEX].Operation;
+  }
+
+  AsmWbinvd ();
+
+  return Status;
+}
+
+#ifdef _MSC_VER
+  #pragma optimize( "", on )
+#endif
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC pop_options
+  #endif
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.h
new file mode 100644
index 0000000000..a604f3be4b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/FwBlockService.h
@@ -0,0 +1,515 @@
+/** @file
+  Implements FvbServicesSmm
+  Firmware volume block driver for SPI device
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FW_BLOCK_SERVICE_SMM_H_
+#define FW_BLOCK_SERVICE_SMM_H_
+
+//
+// The Library classes this module consumes
+//
+#include <Library/UefiLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/Spi.h>
+#include <Protocol/SpiCommon.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#include <Pi/PiFirmwareVolume.h>
+
+#define FVB_PHYSICAL  0
+#define FVB_VIRTUAL   1
+
+typedef struct {
+  EFI_LOCK                      FvbDevLock;
+  UINTN                         FvBase[2];
+  UINTN                         NumOfBlocks;
+  EFI_FIRMWARE_VOLUME_HEADER    VolumeHeader;
+} EFI_FW_VOL_INSTANCE;
+
+typedef struct {
+  UINT32                 NumFv;
+  EFI_FW_VOL_INSTANCE    *FvInstance[2];
+  UINT8                  *FvbScratchSpace[2];
+  EFI_SPI_PROTOCOL       *SpiProtocol;
+} ESAL_FWB_GLOBAL;
+
+//
+// Fvb Protocol instance data
+//
+#define FVB_DEVICE_FROM_THIS(a)         CR (a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE)
+#define FVB_EXTEND_DEVICE_FROM_THIS(a)  CR (a, EFI_FW_VOL_BLOCK_DEVICE, FvbExtension, FVB_DEVICE_SIGNATURE)
+#define FVB_DEVICE_SIGNATURE  SIGNATURE_32 ('F', 'V', 'B', 'N')
+
+typedef struct {
+  MEDIA_FW_VOL_DEVICE_PATH    FvDevPath;
+  EFI_DEVICE_PATH_PROTOCOL    EndDevPath;
+} FV_PIWG_DEVICE_PATH;
+
+typedef struct {
+  MEMMAP_DEVICE_PATH          MemMapDevPath;
+  EFI_DEVICE_PATH_PROTOCOL    EndDevPath;
+} FV_MEMMAP_DEVICE_PATH;
+
+typedef struct {
+  UINTN                                 Signature;
+  EFI_DEVICE_PATH_PROTOCOL              *DevicePath;
+  UINTN                                 Instance;
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    FwVolBlockInstance;
+} EFI_FW_VOL_BLOCK_DEVICE;
+
+/**
+  Get Fvb information.
+
+  @param[in] BaseAddress    The base address compare with NvStorageVariable base address.
+  @param[out] FvbInfo        Fvb information.
+
+  @retval EFI_SUCCESS       Get Fvb information successfully.
+  @retval EFI_NOT_FOUND     Not find Fvb information.
+
+**/
+EFI_STATUS
+GetFvbInfo (
+  IN  UINT64                      FvLength,
+  OUT EFI_FIRMWARE_VOLUME_HEADER  **FvbInfo
+  );
+
+/**
+  Reads specified number of bytes into a buffer from the specified block
+
+  @param[in]       Instance      The FV instance to be read from
+  @param[in]       Lba           The logical block address to be read from
+  @param[in]       BlockOffset   Offset into the block at which to begin reading
+  @param[in, out]  NumBytes      Pointer that on input contains the total size of
+                                 the buffer. On output, it contains the total number
+                                 of bytes read
+  @param[in]       Buffer        Pointer to a caller allocated buffer that will be
+                                 used to hold the data read
+  @param[in]       Global        Pointer to ESAL_FWB_GLOBAL that contains all
+                                 instance data
+  @param[in]       Virtual       Whether CPU is in virtual or physical mode
+
+  @retval   EFI_SUCCESS            The firmware volume was read successfully and
+                                   contents are in Buffer
+  @retval   EFI_BAD_BUFFER_SIZE    Read attempted across a LBA boundary. On output,
+                                   NumBytes contains the total number of bytes returned
+                                   in Buffer
+  @retval   EFI_ACCESS_DENIED      The firmware volume is in the ReadDisabled state
+  @retval   EFI_DEVICE_ERROR       The block device is not functioning correctly and
+                                   could not be read
+  @retval   EFI_INVALID_PARAMETER  Instance not found, or NumBytes, Buffer are NULL
+
+**/
+EFI_STATUS
+FvbReadBlock (
+  IN UINTN            Instance,
+  IN EFI_LBA          Lba,
+  IN UINTN            BlockOffset,
+  IN OUT UINTN        *NumBytes,
+  IN UINT8            *Buffer,
+  IN ESAL_FWB_GLOBAL  *Global,
+  IN BOOLEAN          Virtual
+  );
+
+/**
+  Writes specified number of bytes from the input buffer to the block
+
+  @param[in]       Instance      The FV instance to be written to
+  @param[in]       Lba           The starting logical block index to write to
+  @param[in]       BlockOffset   Offset into the block at which to begin writing
+  @param[in, out]  NumBytes      Pointer that on input contains the total size of
+                                 the buffer. On output, it contains the total number
+                                 of bytes actually written
+  @param[in]       Buffer        Pointer to a caller allocated buffer that contains
+                                 the source for the write
+  @param[in]       Global        Pointer to ESAL_FWB_GLOBAL that contains all
+                                 instance data
+  @param[in]       Virtual       Whether CPU is in virtual or physical mode
+
+  @retval  EFI_SUCCESS             The firmware volume was written successfully
+  @retval  EFI_BAD_BUFFER_SIZE     Write attempted across a LBA boundary. On output,
+                                   NumBytes contains the total number of bytes
+                                   actually written
+  @retval  EFI_ACCESS_DENIED       The firmware volume is in the WriteDisabled state
+  @retval  EFI_DEVICE_ERROR        The block device is not functioning correctly and
+                                   could not be written
+  @retval  EFI_INVALID_PARAMETER   Instance not found, or NumBytes, Buffer are NULL
+
+**/
+EFI_STATUS
+FvbWriteBlock (
+  IN UINTN            Instance,
+  IN EFI_LBA          Lba,
+  IN UINTN            BlockOffset,
+  IN OUT UINTN        *NumBytes,
+  IN UINT8            *Buffer,
+  IN ESAL_FWB_GLOBAL  *Global,
+  IN BOOLEAN          Virtual
+  );
+
+/**
+  Erases and initializes a firmware volume block
+
+  @param[in]  Instance    The FV instance to be erased
+  @param[in]  Lba         The logical block index to be erased
+  @param[in]  Global      Pointer to ESAL_FWB_GLOBAL that contains all
+                          instance data
+  @param[in]  Virtual     Whether CPU is in virtual or physical mode
+
+  @retval  EFI_SUCCESS             The erase request was successfully completed
+  @retval  EFI_ACCESS_DENIED       The firmware volume is in the WriteDisabled state
+  @retval  EFI_DEVICE_ERROR        The block device is not functioning correctly and
+                                   could not be written. Firmware device may have been
+                                   partially erased
+  @retval  EFI_INVALID_PARAMETER   Instance not found
+
+**/
+EFI_STATUS
+FvbEraseBlock (
+  IN UINTN            Instance,
+  IN EFI_LBA          Lba,
+  IN ESAL_FWB_GLOBAL  *Global,
+  IN BOOLEAN          Virtual
+  );
+
+/**
+  Modifies the current settings of the firmware volume according to the
+  input parameter, and returns the new setting of the volume
+
+  @param[in]       Instance          The FV instance whose attributes is going to be
+                                     modified
+  @param[in, out]  Attributes        On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
+                                     containing the desired firmware volume settings.
+                                     On successful return, it contains the new settings
+                                     of the firmware volume
+  @param[in]       Global            Pointer to ESAL_FWB_GLOBAL that contains all
+                                     instance data
+  @param[in]       Virtual           Whether CPU is in virtual or physical mode
+
+  @retval  EFI_SUCCESS             Successfully returns
+  @retval  EFI_ACCESS_DENIED       The volume setting is locked and cannot be modified
+  @retval  EFI_INVALID_PARAMETER   Instance not found, or The attributes requested are
+                                   in conflict with the capabilities as declared in the
+                                   firmware volume header
+
+**/
+EFI_STATUS
+FvbSetVolumeAttributes (
+  IN UINTN                     Instance,
+  IN OUT EFI_FVB_ATTRIBUTES_2  *Attributes,
+  IN ESAL_FWB_GLOBAL           *Global,
+  IN BOOLEAN                   Virtual
+  );
+
+/**
+  Retrieves attributes, insures positive polarity of attribute bits, returns
+  resulting attributes in output parameter
+
+  @param[in]  Instance   The FV instance whose attributes is going to be
+                         returned
+  @param[out] Attributes Output buffer which contains attributes
+  @param[in]  Global     Pointer to ESAL_FWB_GLOBAL that contains all
+                         instance data
+  @param[in]  Virtual    Whether CPU is in virtual or physical mode
+
+  @retval    EFI_SUCCESS            Successfully returns
+  @retval    EFI_INVALID_PARAMETER  Instance not found
+
+**/
+EFI_STATUS
+FvbGetVolumeAttributes (
+  IN UINTN                  Instance,
+  OUT EFI_FVB_ATTRIBUTES_2  *Attributes,
+  IN ESAL_FWB_GLOBAL        *Global,
+  IN BOOLEAN                Virtual
+  );
+
+/**
+  Retrieves the physical address of the device.
+
+  @param[in]   This        Calling context
+  @param[out]  Address     Output buffer containing the address.
+
+  @retval EFI_SUCCESS  Successfully returns
+
+**/
+EFI_STATUS
+FvbGetPhysicalAddress (
+  IN UINTN                  Instance,
+  OUT EFI_PHYSICAL_ADDRESS  *Address,
+  IN ESAL_FWB_GLOBAL        *Global,
+  IN BOOLEAN                Virtual
+  );
+
+/**
+
+  This function does common initialization for FVB services
+
+  @param[in]  ImageHandle            A pointer to a image volume header
+  @param[in]  SystemTable            Pointer to the System Table
+
+  @retval  EFI_SUCCESS               initialization for FVB services successfully
+
+**/
+EFI_STATUS
+EFIAPI
+FvbInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+/**
+  Retrieves the starting address of an LBA in an FV
+
+  @param[in]   Instance               The FV instance which the Lba belongs to
+  @param[in]   Lba                    The logical block address
+  @param[out]  LbaAddress             On output, contains the physical starting address
+                                      of the Lba
+  @param[out]  LbaLength              On output, contains the length of the block
+  @param[out]  NumOfBlocks            A pointer to a caller allocated UINTN in which the
+                                      number of consecutive blocks starting with Lba is
+                                      returned. All blocks in this range have a size of
+                                      BlockSize
+  @param[in]  Global                  Pointer to ESAL_FWB_GLOBAL that contains all
+                                      instance data
+  @param[in]  Virtual                 Whether CPU is in virtual or physical mode
+  @retval  EFI_SUCCESS             Successfully returns
+  @retval  EFI_INVALID_PARAMETER   Instance not found
+
+**/
+EFI_STATUS
+FvbGetLbaAddress (
+  IN  UINTN            Instance,
+  IN  EFI_LBA          Lba,
+  OUT UINTN            *LbaAddress,
+  OUT UINTN            *LbaLength,
+  OUT UINTN            *NumOfBlocks,
+  IN  ESAL_FWB_GLOBAL  *Global,
+  IN  BOOLEAN          Virtual
+  );
+
+/**
+  Retrieves Volume attributes.  No polarity translations are done.
+
+  @param[in]     This                 Calling context
+  @param[out]    Attributes           Output buffer which contains attributes
+
+  @retval  EFI_SUCCESS            Successfully returns
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetAttributes (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  OUT EFI_FVB_ATTRIBUTES_2                     *Attributes
+  );
+
+/**
+  Sets Volume attributes. No polarity translations are done.
+
+  @param[in]   This                   Calling context
+  @param[out]  Attributes             output buffer which contains attributes
+
+  @retval  EFI_SUCCESS                Successfully returns
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolSetAttributes (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  IN OUT EFI_FVB_ATTRIBUTES_2                  *Attributes
+  );
+
+/**
+  Retrieves the physical address of the device.
+
+  @param[in]   This        Calling context
+  @param[out]  Address     Output buffer containing the address.
+
+  @retval EFI_SUCCESS  Successfully returns
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetPhysicalAddress (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  OUT EFI_PHYSICAL_ADDRESS                     *Address
+  );
+
+/**
+  Retrieve the size of a logical block
+
+  @param[in]   This           alling context
+  @param[in]   Lba            Indicates which block to return the size for.
+  @param[out]  BlockSize      A pointer to a caller allocated UINTN in which
+                              the size of the block is returned
+  @param[out]  NumOfBlocks    a pointer to a caller allocated UINTN in which the
+                              number of consecutive blocks starting with Lba is
+                              returned. All blocks in this range have a size of
+                              BlockSize
+
+  @retval  EFI_SUCCESS        The firmware volume was read successfully and
+                              contents are in Buffer
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetBlockSize (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  IN CONST EFI_LBA                             Lba,
+  OUT UINTN                                    *BlockSize,
+  OUT UINTN                                    *NumOfBlocks
+  );
+
+/**
+  Reads data beginning at Lba:Offset from FV. The Read terminates either
+  when *NumBytes of data have been read, or when a block boundary is
+  reached.  *NumBytes is updated to reflect the actual number of bytes
+  written. The write opertion does not include erase. This routine will
+  attempt to write only the specified bytes. If the writes do not stick,
+  it will return an error.
+
+  @param[in]   This       Calling context
+  @param[in]   Lba        Block in which to begin Read
+  @param[in]   Offset     Offset in the block at which to begin Read
+  @param[out]  NumBytes   On input, indicates the requested write size. On
+                          output, indicates the actual number of bytes Read
+  @param[in]  Buffer      Buffer containing source data for the Read.
+
+  @retval  EFI_SUCCESS             The firmware volume was read successfully and
+                                   contents are in Buffer
+  @retval  EFI_BAD_BUFFER_SIZE     Read attempted across a LBA boundary. On output,
+                                   NumBytes contains the total number of bytes returned
+                                   in Buffer
+  @retval  EFI_ACCESS_DENIED       The firmware volume is in the ReadDisabled state
+  @retval  EFI_DEVICE_ERROR        The block device is not functioning correctly and
+                                   could not be read
+  @retval  EFI_INVALID_PARAMETER   NumBytes or Buffer are NULL
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolRead (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  IN CONST EFI_LBA                             Lba,
+  IN CONST UINTN                               Offset,
+  IN OUT UINTN                                 *NumBytes,
+  IN UINT8                                     *Buffer
+  );
+
+/**
+  Writes data beginning at Lba:Offset from FV. The write terminates either
+  when *NumBytes of data have been written, or when a block boundary is
+  reached.  *NumBytes is updated to reflect the actual number of bytes
+  written. The write opertion does not include erase. This routine will
+  attempt to write only the specified bytes. If the writes do not stick,
+  it will return an error.
+
+  @param[in]       This                   Calling context
+  @param[in]       Lba                    Block in which to begin write
+  @param[in]       Offset                 Offset in the block at which to begin write
+  @param[in, out]  NumBytes               On input, indicates the requested write size. On
+                                          output, indicates the actual number of bytes written
+  @param[in]       Buffer                 Buffer containing source data for the write.
+
+  @retval  EFI_SUCCESS            The firmware volume was written successfully
+  @retval  EFI_BAD_BUFFER_SIZE    Write attempted across a LBA boundary. On output,
+                                  NumBytes contains the total number of bytes
+                                  actually written
+  @retval  EFI_ACCESS_DENIED      The firmware volume is in the WriteDisabled state
+  @retval  EFI_DEVICE_ERROR       The block device is not functioning correctly and
+                                  could not be written
+  @retval  EFI_INVALID_PARAMETER  NumBytes or Buffer are NULL
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolWrite (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  IN       EFI_LBA                             Lba,
+  IN       UINTN                               Offset,
+  IN OUT   UINTN                               *NumBytes,
+  IN       UINT8                               *Buffer
+  );
+
+/**
+  The EraseBlock() function erases one or more blocks as denoted by the
+  variable argument list. The entire parameter list of blocks must be verified
+  prior to erasing any blocks.  If a block is requested that does not exist
+  within the associated firmware volume (it has a larger index than the last
+  block of the firmware volume), the EraseBlock() function must return
+  EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
+
+  @param[in]  This                    Calling context
+  @param[in]  ...                     Starting LBA followed by Number of Lba to erase.
+                                      a -1 to terminate the list.
+
+  @retval  EFI_SUCCESS             The erase request was successfully completed
+  @retval  EFI_ACCESS_DENIED       The firmware volume is in the WriteDisabled state
+  @retval  EFI_DEVICE_ERROR        The block device is not functioning correctly and
+                                   could not be written. Firmware device may have been
+                                   partially erased.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolEraseBlocks (
+  IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,
+  ...
+  );
+
+/**
+  Writes specified number of bytes from the input buffer to the address
+
+  @param[in]       WriteAddress      The FV address to be written to
+  @param[in]       Address           The FV address to be written to
+  @param[in, out]  NumBytes          Pointer that on input contains the total size of
+                                     the buffer. On output, it contains the total number
+                                     of bytes actually written
+  @param[in]       Buffer            Pointer to a caller allocated buffer that contains
+                                     the source for the write
+  @param[in]       LbaLength         contains the length of the Buffer.
+
+  @return The status returned from SpiProtocol().
+
+**/
+EFI_STATUS
+FlashFdWrite (
+  IN  UINTN     WriteAddress,
+  IN  UINTN     Address,
+  IN OUT UINTN  *NumBytes,
+  IN  UINT8     *Buffer,
+  IN  UINTN     LbaLength
+  );
+
+/**
+  Erase specified FV address
+
+  @param[in]       WriteAddress      The FV address to be written to
+  @param[in]       LbaLength         contains the length of the Buffer.
+
+  @return The status returned from SpiProtocol().
+
+**/
+EFI_STATUS
+FlashFdErase (
+  IN UINTN  WriteAddress,
+  IN UINTN  LbaLength
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/PlatformSmmSpi.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/PlatformSmmSpi.inf
new file mode 100644
index 0000000000..0a620662d2
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/FvbServices/PlatformSmmSpi.inf
@@ -0,0 +1,68 @@
+## @file
+#  FvbServicesSmm
+#  Component description file for SpiFvbServices Module
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FvbServicesSmm
+  FILE_GUID                      = 72A87810-D3A3-36BE-4788-49AA4003DFD3
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  VERSION_STRING                 = 1.0
+  PI_SPECIFICATION_VERSION       = 0x0001000A
+  ENTRY_POINT                    = FvbInitialize
+
+[Sources]
+  FwBlockService.c
+  FwBlockService.h
+  FvbInfo.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  UefiLib
+  UefiDriverEntryPoint
+  BaseLib
+  DebugLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  DxeServicesTableLib
+  UefiBootServicesTableLib
+  SmmServicesTableLib
+  DevicePathLib
+  HobLib
+  PcdLib
+
+[Guids]
+  gEfiEventVirtualAddressChangeGuid             # ALWAYS_CONSUMED  Create Event: EVENT_GROUP_GUID
+  gEfiSystemNvDataFvGuid
+
+[Protocols]
+  gEfiSmmFirmwareVolumeBlockProtocolGuid
+  gEfiSmmSpiProtocolGuid
+
+[FixedPcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+
+
+[Depex]
+  gEfiSmmBase2ProtocolGuid AND
+  gEfiSmmSpiProtocolGuid
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114587): https://edk2.groups.io/g/devel/message/114587
Mute This Topic: https://groups.io/mt/103975452/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 12/32] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (10 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 11/32] AMD/VanGoghBoard: Check in FvbServices Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib Zhai, MingXin (Duke) via groups.io
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial FCH UART port for Serial log output.
  Chachani board uses this UART for outputting debug log.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../BaseSerialPortLib16550AmdFchUart.c        | 463 ++++++++++++++++++
 .../BaseSerialPortLib16550AmdFchUart.inf      |  40 ++
 2 files changed, 503 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.inf

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.c
new file mode 100644
index 0000000000..665f47f703
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.c
@@ -0,0 +1,463 @@
+/** @file
+  16550 UART Serial Port library functions
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (C) 2014 Hewlett-Packard Development Company, L.P.<BR>
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020, ARM Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/SerialPortLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/PlatformHookLib.h>
+
+//
+// 16550 UART register offsets and bitfields
+//
+#define R_UART_RXBUF         0
+#define R_UART_TXBUF         0
+#define R_UART_BAUD_LOW      0
+#define R_UART_BAUD_HIGH     1
+#define R_UART_FCR           2
+#define   B_UART_FCR_FIFOE   BIT0
+#define   B_UART_FCR_FIFO64  BIT5
+#define R_UART_LCR           3
+#define   B_UART_LCR_DLAB    BIT7
+#define R_UART_MCR           4
+#define   B_UART_MCR_RTS     BIT1
+#define R_UART_LSR           5
+#define   B_UART_LSR_RXRDY   BIT0
+#define   B_UART_LSR_TXRDY   BIT5
+#define   B_UART_LSR_TEMT    BIT6
+#define R_UART_MSR           6
+#define   B_UART_MSR_CTS     BIT4
+#define   B_UART_MSR_DSR     BIT5
+
+/**
+  Read an 8-bit 16550 register.  The parameter Offset is added to the base address of the
+  16550 registers that is specified by PcdSerialRegisterBase.
+  @param  Offset  The offset of the 16550 register to read.
+  @return The value read from the 16550 register.
+**/
+UINT8
+SerialPortReadRegister (
+  UINTN  Offset
+  )
+{
+  return MmioRead8 ((UINTN)PcdGet64 (PcdSerialRegisterBase) + Offset * 4);
+}
+
+/**
+  Write an 8-bit 16550 register. The parameter Offset is added to the base address of the
+  16550 registers that is specified by PcdSerialRegisterBase.
+  @param  Offset  The offset of the 16550 register to write.
+  @param  Value   The value to write to the 16550 register specified by Offset.
+  @return The value written to the 16550 register.
+**/
+UINT8
+SerialPortWriteRegister (
+  UINTN  Offset,
+  UINT8  Value
+  )
+{
+  return MmioWrite8 ((UINTN)PcdGet64 (PcdSerialRegisterBase) + Offset * 4, Value);
+}
+
+/**
+  Return whether the hardware flow control signal allows writing.
+
+  @retval TRUE  The serial port is writable.
+  @retval FALSE The serial port is not writable.
+**/
+BOOLEAN
+SerialPortWritable (
+  VOID
+  )
+{
+  if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
+    if (PcdGetBool (PcdSerialDetectCable)) {
+      //
+      // Wait for both DSR and CTS to be set
+      //   DSR is set if a cable is connected.
+      //   CTS is set if it is ok to transmit data
+      //
+      //   DSR  CTS  Description                               Action
+      //   ===  ===  ========================================  ========
+      //    0    0   No cable connected.                       Wait
+      //    0    1   No cable connected.                       Wait
+      //    1    0   Cable connected, but not clear to send.   Wait
+      //    1    1   Cable connected, and clear to send.       Transmit
+      //
+      return (BOOLEAN)((SerialPortReadRegister (R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) == (B_UART_MSR_DSR | B_UART_MSR_CTS));
+    } else {
+      //
+      // Wait for both DSR and CTS to be set OR for DSR to be clear.
+      //   DSR is set if a cable is connected.
+      //   CTS is set if it is ok to transmit data
+      //
+      //   DSR  CTS  Description                               Action
+      //   ===  ===  ========================================  ========
+      //    0    0   No cable connected.                       Transmit
+      //    0    1   No cable connected.                       Transmit
+      //    1    0   Cable connected, but not clear to send.   Wait
+      //    1    1   Cable connected, and clar to send.        Transmit
+      //
+      return (BOOLEAN)((SerialPortReadRegister (R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) != (B_UART_MSR_DSR));
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+  RCheck Cable connection.
+
+  @retval TRUE  RCheck Cable not connect.
+  @retval FALSE RCheck Cable connect.
+**/
+BOOLEAN
+CheckCableConnection (
+  )
+{
+  UINT32  RetryCount;
+
+  // Check Cable connection
+  RetryCount = 200;
+  if (PcdGetBool (PcdSerialDetectCable)) {
+    do {
+      RetryCount--;
+    } while (((SerialPortReadRegister (R_UART_MSR) & (B_UART_MSR_DSR | B_UART_MSR_CTS)) != (B_UART_MSR_DSR | B_UART_MSR_CTS)) && (RetryCount > 0));
+  }
+
+  if (RetryCount == 0) {
+    // Time expired
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Check Serial Port status.
+
+  @retval TRUE  The serial port is enable.
+  @retval FALSE The serial port is not enable.
+**/
+BOOLEAN
+CheckSerialPort (
+  )
+{
+  UINTN   Divisor;
+  UINT32  SerialClkDiv16;
+
+  SerialClkDiv16 = 48000000/ 16;
+  //
+  // See if the serial port is already initialized
+  //
+  if ((SerialPortReadRegister (R_UART_FCR) & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)) !=
+      (PcdGet8 (PcdSerialFifoControl)      & (B_UART_FCR_FIFOE | B_UART_FCR_FIFO64)))
+  {
+    return FALSE;
+  }
+
+  if ((SerialPortReadRegister (R_UART_LCR) & 0x3F) != (PcdGet8 (PcdSerialLineControl) & 0x3F)) {
+    return FALSE;
+  }
+
+  SerialPortWriteRegister (R_UART_LCR, (UINT8)(SerialPortReadRegister (R_UART_LCR) | B_UART_LCR_DLAB));
+  Divisor  =  SerialPortReadRegister (R_UART_BAUD_HIGH) << 8;
+  Divisor |= SerialPortReadRegister (R_UART_BAUD_LOW);
+  SerialPortWriteRegister (R_UART_LCR, (UINT8)(SerialPortReadRegister (R_UART_LCR) & ~B_UART_LCR_DLAB));
+  if (Divisor != SerialClkDiv16 / PcdGet32 (PcdSerialBaudRate)) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Initial Serial Port.
+
+**/
+VOID
+InitSerialPort (
+  )
+{
+  UINTN   Divisor;
+  UINT32  SerialClkDiv16;
+
+  SerialClkDiv16 = 48000000 / 16;
+  //
+  // Configure baud rate
+  //
+  Divisor = SerialClkDiv16 / PcdGet32 (PcdSerialBaudRate);
+  SerialPortWriteRegister (R_UART_LCR, B_UART_LCR_DLAB);
+  SerialPortWriteRegister (R_UART_BAUD_HIGH, (UINT8)(Divisor >> 8));
+  SerialPortWriteRegister (R_UART_BAUD_LOW, (UINT8)(Divisor & 0xff));
+
+  //
+  // Clear DLAB and configure Data Bits, Parity, and Stop Bits.
+  // Strip reserved bits from PcdSerialLineControl
+  //
+  SerialPortWriteRegister (R_UART_LCR, (UINT8)(PcdGet8 (PcdSerialLineControl) & 0x3F));
+
+  //
+  // Enable and reset FIFOs
+  // Strip reserved bits from PcdSerialFifoControl
+  //
+  SerialPortWriteRegister (R_UART_FCR, (UINT8)(PcdGet8 (PcdSerialFifoControl) & 0x27));
+
+  //
+  // Put Modem Control Register(MCR) into its reset state of 0x00.
+  //
+  SerialPortWriteRegister (R_UART_MCR, 0x00);
+}
+
+/**
+  Initialize the serial device hardware.
+
+  If no initialization is required, then return RETURN_SUCCESS.
+  If the serial device was successfully initialized, then return RETURN_SUCCESS.
+  If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+  @retval RETURN_DEVICE_ERROR   The serial device could not be initialized.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+  VOID
+  )
+{
+  RETURN_STATUS  Status;
+
+  Status = PlatformHookSerialPortInitialize ();
+  if (RETURN_ERROR (Status)) {
+    return Status;
+  }
+
+  if (!CheckCableConnection ()) {
+    return RETURN_DEVICE_ERROR;
+  }
+
+  if (!CheckSerialPort ()) {
+    InitSerialPort ();
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Write data from buffer to serial device.
+
+  Writes NumberOfBytes data bytes from Buffer to the serial device.
+  The number of bytes actually written to the serial device is returned.
+  If the return value is less than NumberOfBytes, then the write operation failed.
+
+  If Buffer is NULL, then ASSERT().
+
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer           Pointer to the data buffer to be written.
+  @param  NumberOfBytes    Number of bytes to written to the serial device.
+
+  @retval 0                NumberOfBytes is 0.
+  @retval >0               The number of bytes written to the serial device.
+                           If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortWrite (
+  IN UINT8  *Buffer,
+  IN UINTN  NumberOfBytes
+  )
+{
+  UINTN   Result;
+  UINTN   Index;
+  UINTN   FifoSize;
+  UINT32  RetryCount;
+
+  if (Buffer == NULL) {
+    return 0;
+  }
+
+  if (!CheckCableConnection ()) {
+    return 0;
+  }
+
+  if (NumberOfBytes == 0) {
+    //
+    // Flush the hardware
+    //
+
+    //
+    // Wait for both the transmit FIFO and shift register empty.
+    //
+    RetryCount = 2000;
+    do {
+      RetryCount--;
+    } while (((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_TEMT) == 0) && (RetryCount > 0));
+
+    if (RetryCount == 0) {
+      InitSerialPort ();
+    }
+
+    //
+    // Wait for the hardware flow control signal
+    //
+    while (!SerialPortWritable ()) {
+    }
+
+    return 0;
+  }
+
+  //
+  // Compute the maximum size of the Tx FIFO
+  //
+  FifoSize = 1;
+  if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFOE) != 0) {
+    if ((PcdGet8 (PcdSerialFifoControl) & B_UART_FCR_FIFO64) == 0) {
+      FifoSize = 16;
+    } else {
+      FifoSize = 64;
+    }
+  }
+
+  Result = NumberOfBytes;
+  while (NumberOfBytes != 0) {
+    //
+    // Wait for the serial port to be ready, to make sure both the transmit FIFO
+    // and shift register empty.
+    //
+    RetryCount = 2000;
+    do {
+      RetryCount--;
+    } while (((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_TEMT) == 0) && (RetryCount > 0));
+
+    if (RetryCount == 0) {
+      InitSerialPort ();
+    }
+
+    //
+    // Fill then entire Tx FIFO
+    //
+    for (Index = 0; Index < FifoSize && NumberOfBytes != 0; Index++, NumberOfBytes--, Buffer++) {
+      //
+      // Wait for the hardware flow control signal
+      //
+      while (!SerialPortWritable ()) {
+      }
+
+      //
+      // Write byte to the transmit buffer.
+      //
+      SerialPortWriteRegister (R_UART_TXBUF, *Buffer);
+    }
+  }
+
+  return Result;
+}
+
+/**
+  Reads data from a serial device into a buffer.
+
+  @param  Buffer           Pointer to the data buffer to store the data read from the serial device.
+  @param  NumberOfBytes    Number of bytes to read from the serial device.
+
+  @retval 0                NumberOfBytes is 0.
+  @retval >0               The number of bytes read from the serial device.
+                           If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+SerialPortRead (
+  OUT UINT8  *Buffer,
+  IN  UINTN  NumberOfBytes
+  )
+{
+  UINTN  Result;
+  UINT8  Mcr;
+
+  if (NULL == Buffer) {
+    return 0;
+  }
+
+  Mcr = (UINT8)(SerialPortReadRegister (R_UART_MCR) & ~B_UART_MCR_RTS);
+
+  for (Result = 0; NumberOfBytes-- != 0; Result++, Buffer++) {
+    //
+    // Wait for the serial port to have some data.
+    //
+    while ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_RXRDY) == 0) {
+      if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
+        //
+        // Set RTS to let the peer send some data
+        //
+        SerialPortWriteRegister (R_UART_MCR, (UINT8)(Mcr | B_UART_MCR_RTS));
+      }
+    }
+
+    if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
+      //
+      // Clear RTS to prevent peer from sending data
+      //
+      SerialPortWriteRegister (R_UART_MCR, Mcr);
+    }
+
+    //
+    // Read byte from the receive buffer.
+    //
+    *Buffer = SerialPortReadRegister (R_UART_RXBUF);
+  }
+
+  return Result;
+}
+
+/**
+  Polls a serial device to see if there is any data waiting to be read.
+
+  Polls aserial device to see if there is any data waiting to be read.
+  If there is data waiting to be read from the serial device, then TRUE is returned.
+  If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+  @retval TRUE             Data is waiting to be read from the serial device.
+  @retval FALSE            There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+  VOID
+  )
+{
+  //
+  // Read the serial port status
+  //
+  if ((SerialPortReadRegister (R_UART_LSR) & B_UART_LSR_RXRDY) != 0) {
+    if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
+      //
+      // Clear RTS to prevent peer from sending data
+      //
+      SerialPortWriteRegister (R_UART_MCR, (UINT8)(SerialPortReadRegister (R_UART_MCR) & ~B_UART_MCR_RTS));
+    }
+
+    return TRUE;
+  }
+
+  if (PcdGetBool (PcdSerialUseHardwareFlowControl)) {
+    //
+    // Set RTS to let the peer send some data
+    //
+    SerialPortWriteRegister (R_UART_MCR, (UINT8)(SerialPortReadRegister (R_UART_MCR) | B_UART_MCR_RTS));
+  }
+
+  return FALSE;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.inf
new file mode 100644
index 0000000000..e6f824401d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/BaseSerialPortLib16550AmdFchUart/BaseSerialPortLib16550AmdFchUart.inf
@@ -0,0 +1,40 @@
+## @file
+#  SerialPortLib instance for 16550 UART.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2020, ARM Limited. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseSerialPortLib16550AmdFchUart
+  FILE_GUID                      = A66281AD-66E9-4089-9B1C-9CFC84D8A760
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SerialPortLib
+
+[Sources]
+  BaseSerialPortLib16550AmdFchUart.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  IoLib
+  PlatformHookLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialDetectCable
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl
\ No newline at end of file
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114588): https://edk2.groups.io/g/devel/message/114588
Mute This Topic: https://groups.io/mt/103975453/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (11 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 12/32] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 14/32] AMD/VanGoghBoard: Check in SmbiosLib Zhai, MingXin (Duke) via groups.io
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial AMD PlatformFlashAccessLib, It provides flash access protocol for other modules.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Include/Library/SpiFlashDeviceLib.h       |  59 ++
 .../VanGoghCommonPkg/Include/Protocol/Spi.h   | 346 ++++++++++++
 .../Include/Protocol/SpiCommon.h              | 247 ++++++++
 .../Include/Protocol/SpiFlashUpdate.h         | 152 +++++
 .../PlatformFlashAccessLib.c                  | 528 ++++++++++++++++++
 .../PlatformFlashAccessLib.inf                |  52 ++
 6 files changed, 1384 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDeviceLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashUpdate.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDeviceLib.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDeviceLib.h
new file mode 100644
index 0000000000..391453f512
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SpiFlashDeviceLib.h
@@ -0,0 +1,59 @@
+/** @file
+  Implements SpiFlashDevice.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_FLASH_DEVICE_LIB_H_
+#define SPI_FLASH_DEVICE_LIB_H_
+
+#include <Protocol/Spi.h>
+
+//
+// Provides mSpiInitTable and the total number of flash part in mSpiInitTable for other modules.
+//
+extern SPI_INIT_TABLE  mSpiInitTable[];
+extern UINT8           mNumSpiFlashMax;
+
+//
+// Flash Device commands
+//
+// If a supported device uses a command different from the list below, a device specific command
+// will be defined just below it's JEDEC id section.
+//
+#define SPI_COMMAND_WRITE             0x02
+#define SPI_COMMAND_WRITE_AAI         0xAD
+#define SPI_COMMAND_READ              0x03
+#define SPI_COMMAND_ERASE             0x20
+#define SPI_COMMAND_WRITE_DISABLE     0x04
+#define SPI_COMMAND_READ_S            0x05
+#define SPI_COMMAND_WRITE_ENABLE      0x06
+#define SPI_COMMAND_READ_ID           0xAB
+#define SPI_COMMAND_JEDEC_ID          0x9F
+#define SPI_COMMAND_WRITE_S_EN        0x50
+#define SPI_COMMAND_WRITE_S           0x01
+#define SPI_COMMAND_CHIP_ERASE        0xC7
+#define SPI_COMMAND_BLOCK_ERASE       0xD8
+#define SPI_COMMAND_READ_SFDP         0x5A
+#define SPI_COMMAND_RPMC_OP1          0x9B
+#define SPI_COMMAND_RPMC_OP2          0x96
+#define SPI_COMMAND_Enter_4Byte_Addr  0xB7
+#define SPI_COMMAND_Exit_4Byte_Addr   0xE9
+
+//
+// Winbond 256Mbit parts
+//
+#define SF_VENDOR_ID_WINBOND     0xEF
+#define SF_DEVICE_ID1_W25Q256JW  0x19          // Capacity 256Mbit
+#define SF_DEVICE_ID0_W25Q256JW  0x60
+
+//
+// index for prefix opcodes
+//
+#define SPI_WREN_INDEX  0                     // Prefix Opcode 0: SPI_COMMAND_WRITE_ENABLE
+#define SPI_EWSR_INDEX  1                     // Prefix Opcode 1: SPI_COMMAND_WRITE_S_EN
+#define BIOS_CTRL       0xDC
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h
new file mode 100644
index 0000000000..9702d34f7c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/Spi.h
@@ -0,0 +1,346 @@
+/** @file
+  Implements AMD Spi
+  This file defines the EFI SPI Protocol which implements the
+  Intel(R) ICH SPI Host Controller Compatibility Interface.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_H_
+#define SPI_H_
+
+#include <Uefi/UefiBaseType.h>
+
+//
+// Define the SPI protocol GUID
+//
+// EDK and EDKII have different GUID formats
+//
+#if !defined (EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define EFI_SPI_PROTOCOL_GUID \
+  { \
+    0x1156efc6, 0xea32, 0x4396, 0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 \
+  }
+#define EFI_SMM_SPI_PROTOCOL_GUID \
+  { \
+    0xD9072C35, 0xEB8F, 0x43ad, 0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 \
+  }
+#else
+#define EFI_SPI_PROTOCOL_GUID \
+  { \
+    0x1156efc6, 0xea32, 0x4396, \
+    { \
+      0xb5, 0xd5, 0x26, 0x93, 0x2e, 0x83, 0xc3, 0x13 \
+    } \
+  }
+#define EFI_SMM_SPI_PROTOCOL_GUID \
+  { \
+    0xD9072C35, 0xEB8F, 0x43ad, \
+    { \
+      0xA2, 0x20, 0x34, 0xD4, 0x0E, 0x2A, 0x82, 0x85 \
+    } \
+  }
+#endif
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID  gEfiSpiProtocolGuid;
+extern EFI_GUID  gEfiSmmSpiProtocolGuid;
+
+#define FCH_SPI_MMIO_REG00    0x00           // SPI_
+#define FCH_SPI_OPCODE        0x000000FFl    //
+#define FCH_SPI_TX_COUNT      0x00000F00l    //
+#define FCH_SPI_RX_COUNT      0x0000F000l    //
+#define FCH_SPI_EXEC_OPCODE   0x00010000l    //
+#define FCH_SPI_FIFO_PTR_CRL  0x00100000l    //
+#define FCH_SPI_FIFO_PTR_INC  0x00200000l    //
+#define FCH_SPI_BUSY          0x80000000l    //
+#define FCH_SPI_MMIO_REG0C    0x0C           // SPI_Cntrl1 Register
+#define FCH_SPI_PARAMETER     0x000000FFl    //
+#define FCH_SPI_FIFO_PTR      0x00000700l    //
+#define FCH_SPI_BYTE_PROGRAM  0xFF000000l    //
+#define FCH_SPI_MMIO_REG1C    0x1C           //
+#define FCH_SPI_RETRY_TIMES   0x3            //
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _EFI_SPI_PROTOCOL EFI_SPI_PROTOCOL;
+
+//
+// SPI protocol data structures and definitions
+//
+//
+// Number of Prefix Opcodes allowed on the SPI interface
+//
+#define SPI_NUM_PREFIX_OPCODE  2
+
+//
+// Number of Opcodes in the Opcode Menu
+//
+#define SPI_NUM_OPCODE  12
+
+//
+// Opcode Type
+//    EnumSpiOpcodeCommand: Command without address
+//    EnumSpiOpcodeRead: Read with address
+//    EnumSpiOpcodeWrite: Write with address
+//
+typedef enum {
+  EnumSpiOpcodeReadNoAddr,
+  EnumSpiOpcodeWriteNoAddr,
+  EnumSpiOpcodeRead,
+  EnumSpiOpcodeWrite,
+  EnumSpiOpcodeMax
+} SPI_OPCODE_TYPE;
+
+typedef enum {
+  EnumSpiRegionAll,
+  EnumSpiRegionBios,
+  EnumSpiRegionMe,
+  EnumSpiRegionGbE,
+  EnumSpiRegionDescriptor,
+  EnumSpiRegionPlatformData,
+  EnumSpiRegionMax
+} SPI_REGION_TYPE;
+
+//
+// Hardware Sequencing required operations (as listed in CougarPoint EDS Table 5-55: "Hardware
+// Sequencing Commands and Opcode Requirements"
+//
+typedef enum {
+  EnumSpiOperationWriteStatus,
+  EnumSpiOperationProgramData_1_Byte,
+  EnumSpiOperationProgramData_64_Byte,
+  EnumSpiOperationReadData,
+  EnumSpiOperationWriteDisable,
+  EnumSpiOperationReadStatus,
+  EnumSpiOperationWriteEnable,
+  EnumSpiOperationFastRead,
+  EnumSpiOperationEnableWriteStatus,
+  EnumSpiOperationErase_256_Byte,
+  EnumSpiOperationErase_4K_Byte  = 0x1000,
+  EnumSpiOperationErase_8K_Byte  = 0x2000,
+  EnumSpiOperationErase_64K_Byte = 0x10000,
+  EnumSpiOperationFullChipErase,
+  EnumSpiOperationJedecId,
+  EnumSpiOperationDualOutputFastRead,
+  EnumSpiOperationDiscoveryParameters,
+  EnumSpiOperationOther,
+  EnumSpiOperationMax
+} SPI_OPERATION;
+
+//
+// Opcode menu entries
+//   Type            Operation Type (value to be programmed to the OPTYPE register)
+//   Code            The opcode (value to be programmed to the OPMENU register)
+//   Operation       Which Hardware Sequencing required operation this opcode respoinds to.
+//                   The required operations are listed in EDS Table 5-55: "Hardware
+//                   Sequencing Commands and Opcode Requirements"
+//                   If the opcode does not corresponds to any operation listed, use
+//                   EnumSpiOperationOther
+//
+typedef struct _SPI_OPCODE_MENU_ENTRY {
+  SPI_OPCODE_TYPE    Type;
+  UINT8              Code;
+  SPI_OPERATION      Operation;
+} SPI_OPCODE_MENU_ENTRY;
+
+//
+// Initialization data table loaded to the SPI host controller
+//    VendorId        Vendor ID of the SPI device
+//    DeviceId0       Device ID0 of the SPI device
+//    DeviceId1       Device ID1 of the SPI device
+//    PrefixOpcode    Prefix opcodes which are loaded into the SPI host controller
+//    OpcodeMenu      Opcodes which are loaded into the SPI host controller Opcode Menu
+//    BiosStartOffset The offset of the start of the BIOS image relative to the flash device.
+//                    Please note this is a Flash Linear Address, NOT a memory space address.
+//                    This value is platform specific and depends on the system flash map.
+//                    This value is only used on non Descriptor mode.
+//    BiosSize        The the BIOS Image size in flash. This value is platform specific
+//                    and depends on the system flash map. Please note BIOS Image size may
+//                    be smaller than BIOS Region size (in Descriptor Mode) or the flash size
+//                    (in Non Descriptor Mode), and in this case, BIOS Image is supposed to be
+//                    placed at the top end of the BIOS Region (in Descriptor Mode) or the flash
+//                    (in Non Descriptor Mode)
+//
+typedef struct _SPI_INIT_TABLE {
+  UINT8                    VendorId;
+  UINT8                    DeviceId0;
+  UINT8                    DeviceId1;
+  UINT8                    PrefixOpcode[SPI_NUM_PREFIX_OPCODE];
+  SPI_OPCODE_MENU_ENTRY    OpcodeMenu[SPI_NUM_OPCODE];
+  UINTN                    BiosStartOffset;
+  UINTN                    BiosSize;
+} SPI_INIT_TABLE;
+
+//
+// Public Info struct to show current initialized state of the spi interface.
+// OpcodeIndex must be less then SPI_NUM_OPCODE for operation to be supported.
+//
+typedef struct _SPI_INIT_INFO {
+  SPI_INIT_TABLE    *InitTable;
+  UINT8             JedecIdOpcodeIndex;
+  UINT8             OtherOpcodeIndex;
+  UINT8             WriteStatusOpcodeIndex;
+  UINT8             ProgramOpcodeIndex;
+  UINT8             ReadOpcodeIndex;
+  UINT8             EraseOpcodeIndex;
+  UINT8             ReadStatusOpcodeIndex;
+  UINT8             FullChipEraseOpcodeIndex;
+} SPI_INIT_INFO;
+
+//
+// Protocol member functions
+//
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_INIT)(
+  IN EFI_SPI_PROTOCOL     *This
+  );
+
+/*++
+
+Routine Description:
+
+  Initializes the host controller to execute SPI commands.
+
+Arguments:
+
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.
+
+Returns:
+
+  EFI_SUCCESS             Opcode initialization on the SPI host controller completed.
+  EFI_ACCESS_DENIED       The SPI configuration interface is locked.
+  EFI_OUT_OF_RESOURCES    Not enough resource available to initialize the device.
+  EFI_DEVICE_ERROR        Device error, operation failed.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_LOCK)(
+  IN EFI_SPI_PROTOCOL     *This
+  );
+
+/*++
+
+Routine Description:
+
+  Lock the SPI Static Configuration Interface.
+  Once locked, the interface is no longer open for configuration changes.
+  The lock state automatically clears on next system reset.
+
+Arguments:
+
+  This      Pointer to the EFI_SPI_PROTOCOL instance.
+
+Returns:
+
+  EFI_SUCCESS             Lock operation succeed.
+  EFI_DEVICE_ERROR        Device error, operation failed.
+  EFI_ACCESS_DENIED       The interface has already been locked.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_EXECUTE)(
+  IN     EFI_SPI_PROTOCOL   *This,
+  IN     UINT8              OpcodeIndex,
+  IN     UINT8              PrefixOpcodeIndex,
+  IN     BOOLEAN            DataCycle,
+  IN     BOOLEAN            Atomic,
+  IN     BOOLEAN            ShiftOut,
+  IN     UINTN              Address,
+  IN     UINT32             DataByteCount,
+  IN OUT UINT8              *Buffer,
+  IN     SPI_REGION_TYPE    SpiRegionType
+  );
+
+/*++
+
+Routine Description:
+
+  Execute SPI commands from the host controller.
+
+Arguments:
+
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.
+  OpcodeIndex             Index of the command in the OpCode Menu.
+  PrefixOpcodeIndex       Index of the first command to run when in an atomic cycle sequence.
+  DataCycle               TRUE if the SPI cycle contains data
+  Atomic                  TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  ShiftOut                If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  Address                 In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                          Region, this value specifies the offset from the Region Base; for BIOS Region,
+                          this value specifies the offset from the start of the BIOS Image. In Non
+                          Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                          Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                          Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                          supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                          the flash (in Non Descriptor Mode)
+  DataByteCount           Number of bytes in the data portion of the SPI cycle.
+  Buffer                  Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle.
+  SpiRegionType           SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                          EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                          Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                          and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                          to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+Returns:
+
+  EFI_SUCCESS             Command succeed.
+  EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  EFI_UNSUPPORTED         Command not supported.
+  EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+
+--*/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_INFO)(
+  IN EFI_SPI_PROTOCOL     *This,
+  OUT SPI_INIT_INFO      **InitInfoPtr
+  );
+
+/*++
+
+Routine Description:
+
+  Return info about SPI host controller, to help callers usage of Execute
+  service.
+
+  If 0xff is returned as an opcode index in init info struct
+  then device does not support the operation.
+
+Arguments:
+
+  This                    Pointer to the EFI_SPI_PROTOCOL instance.
+  InitInfoPtr             Pointer to init info written to this memory location.
+
+Returns:
+
+  EFI_SUCCESS             Information returned.
+  EFI_INVALID_PARAMETER   Invalid parameter.
+  EFI_NOT_READY           Required resources not setup.
+  Others                  Unexpected error happened.
+
+--*/
+
+//
+// Protocol definition
+//
+struct _EFI_SPI_PROTOCOL {
+  EFI_SPI_INIT       Init;
+  EFI_SPI_LOCK       Lock;
+  EFI_SPI_EXECUTE    Execute;
+  EFI_SPI_INFO       Info;
+};
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h
new file mode 100644
index 0000000000..1488c9715b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiCommon.h
@@ -0,0 +1,247 @@
+/** @file
+  Implements AMD SpiCommon
+  Header file for the PCH SPI Common Driver.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013-2015 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_COMMON_H_
+#define SPI_COMMON_H_
+
+#include "Protocol/Spi.h"
+
+#include <Library/PciLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+// #include <Library/SpiFlashDeviceLib.h>
+
+#include <Uefi/UefiBaseType.h>
+
+//
+// Maximum time allowed while waiting the SPI cycle to complete
+//  Wait Time = 6 seconds = 6000000 microseconds
+//  Wait Period = 10 microseconds
+//
+#define WAIT_TIME    6000000
+#define WAIT_PERIOD  10
+
+//
+// Private data structure definitions for the driver
+//
+#define FCH_SPI_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('F', 'S', 'P', 'I')
+
+//
+// SPI default opcode slots
+//
+#define SPI_OPCODE_JEDEC_ID_INDEX           0
+#define SPI_OPCODE_WRITE_S_INDEX            1
+#define SPI_OPCODE_WRITE_INDEX              2
+#define SPI_OPCODE_READ_INDEX               3
+#define SPI_OPCODE_ERASE_INDEX              4
+#define SPI_OPCODE_READ_S_INDEX             5
+#define SPI_OPCODE_CHIP_ERASE_INDEX         6
+#define SPI_OPCODE_READ_SFDP_INDEX          7
+#define SPI_COMMAND_RPMC_OP1_INDEX          8
+#define SPI_COMMAND_RPMC_OP2_INDEX          9
+#define SPI_COMMAND_Enter_4Byte_Addr_INDEX  10
+#define SPI_COMMAND_Exit_4Byte_Addr_INDEX   11
+
+typedef struct {
+  UINTN               Signature;
+  EFI_HANDLE          Handle;
+  EFI_SPI_PROTOCOL    SpiProtocol;
+  SPI_INIT_TABLE      SpiInitTable;
+  UINTN               SpiBar;
+  BOOLEAN             InitDone; // Set to TRUE on SpiProtocolInit SUCCESS.
+  SPI_INIT_INFO       InitInfo;
+} SPI_INSTANCE;
+
+#define SPI_INSTANCE_FROM_SPIPROTOCOL(a)  CR (a, SPI_INSTANCE, SpiProtocol, FCH_SPI_PRIVATE_DATA_SIGNATURE)
+
+/**
+
+  Initialize an SPI protocol instance.
+  The function will assert in debug if FCH SPI has not been initialized
+
+  @param SpiInstance   - Pointer to SpiInstance to initialize
+
+  @retval EFI_SUCCESS     The protocol instance was properly initialized
+  @retval EFI_UNSUPPORTED The FCH is not supported by this module
+
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+  SPI_INSTANCE  *SpiInstance
+  )
+;
+
+/**
+
+  Initialize the host controller to execute SPI command.
+
+  @param This                    Pointer to the EFI_SPI_PROTOCOL instance.
+
+  @retval EFI_SUCCESS             Initialization completed.
+  @retval EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.
+  @retval EFI_INVALID_PARAMETER   Bad input parameters.
+  @retval EFI_UNSUPPORTED         Can't get Descriptor mode VSCC values
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolInit (
+  IN EFI_SPI_PROTOCOL  *This
+  )
+;
+
+/**
+
+  Lock the SPI Static Configuration Interface.
+  Once locked, the interface can not be changed and can only be clear by system reset.
+
+  @param This      Pointer to the EFI_SPI_PROTOCOL instance.
+
+  @retval EFI_SUCCESS             Lock operation succeed.
+  @retval EFI_DEVICE_ERROR        Device error, operation failed.
+  @retval EFI_ACCESS_DENIED       The interface has already been locked.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolLock (
+  IN EFI_SPI_PROTOCOL  *This
+  )
+;
+
+/**
+
+  Execute SPI commands from the host controller.
+  This function would be called by runtime driver, please do not use any MMIO marco here
+
+  @param This              Pointer to the EFI_SPI_PROTOCOL instance.
+  @param OpcodeIndex       Index of the command in the OpCode Menu.
+  @param PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+  @param DataCycle         TRUE if the SPI cycle contains data
+  @param Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  @param ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  @param Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                           Region, this value specifies the offset from the Region Base; for BIOS Region,
+                           this value specifies the offset from the start of the BIOS Image. In Non
+                           Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                           Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                           Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                           supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                           the flash (in Non Descriptor Mode)
+  @param DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
+                           data transfer into multiple operations. This function ensures each operation does
+                           not cross 256 byte flash address boundary.
+                           *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+                           (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+                           function to cut the data transfer at proper address boundaries, and it's the
+                           caller's reponsibility to pass in a properly cut DataByteCount parameter.
+  @param Buffer            Pointer to caller-allocated buffer containing the dada received or sent during the
+                           SPI cycle.
+  @param SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                           EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                           Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                           and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                           to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_UNSUPPORTED         Command not supported.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolExecute (
+  IN     EFI_SPI_PROTOCOL  *This,
+  IN     UINT8             OpcodeIndex,
+  IN     UINT8             PrefixOpcodeIndex,
+  IN     BOOLEAN           DataCycle,
+  IN     BOOLEAN           Atomic,
+  IN     BOOLEAN           ShiftOut,
+  IN     UINTN             Address,
+  IN     UINT32            DataByteCount,
+  IN OUT UINT8             *Buffer,
+  IN     SPI_REGION_TYPE   SpiRegionType
+  )
+;
+
+/**
+
+  This function sends the programmed SPI command to the slave device.
+
+  @param OpcodeIndex       Index of the command in the OpCode Menu.
+  @param PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+  @param DataCycle         TRUE if the SPI cycle contains data
+  @param Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  @param ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  @param Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                           Region, this value specifies the offset from the Region Base; for BIOS Region,
+                           this value specifies the offset from the start of the BIOS Image. In Non
+                           Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                           Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                           Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                           supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                           the flash (in Non Descriptor Mode)
+  @param DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
+                           data transfer into multiple operations. This function ensures each operation does
+                           not cross 256 byte flash address boundary.
+                           *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+                           (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+                           function to cut the data transfer at proper address boundaries, and it's the
+                           caller's reponsibility to pass in a properly cut DataByteCount parameter.
+  @param Buffer            Data received or sent during the SPI cycle.
+  @param SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                           EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                           Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                           and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                           to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+  @retval EFI_SUCCESS             SPI command completes successfully.
+  @retval EFI_DEVICE_ERROR        Device error, the command aborts abnormally.
+  @retval EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+
+**/
+EFI_STATUS
+SendSpiCmd (
+  IN     EFI_SPI_PROTOCOL  *This,
+  IN     UINT8             OpcodeIndex,
+  IN     UINT8             PrefixOpcodeIndex,
+  IN     BOOLEAN           DataCycle,
+  IN     BOOLEAN           Atomic,
+  IN     BOOLEAN           ShiftOut,
+  IN     UINTN             Address,
+  IN     UINT32            DataByteCount,
+  IN OUT UINT8             *Buffer,
+  IN     SPI_REGION_TYPE   SpiRegionType
+  )
+;
+
+/**
+
+  Wait execution cycle to complete on the SPI interface. Check both Hardware
+  and Software Sequencing status registers
+
+  @param This   The SPI protocol instance
+
+  @retval TRUE  SPI cycle completed on the interface.
+  @retval FALSE Time out while waiting the SPI cycle to complete.
+             It's not safe to program the next command on the SPI interface.
+
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+  IN     EFI_SPI_PROTOCOL  *This
+  )
+;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashUpdate.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashUpdate.h
new file mode 100644
index 0000000000..e1271e2244
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Protocol/SpiFlashUpdate.h
@@ -0,0 +1,152 @@
+/** @file
+  Implements AMD PcRtc
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_FLASH_UPDATE_H_
+#define SPI_FLASH_UPDATE_H_
+
+#include <Uefi/UefiBaseType.h>
+
+//
+// Spi Flash Update Protocol GUID
+// EDK and EDKII have different GUID formats
+//
+#if !defined (EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define EFI_SPI_FLASH_UPDATE_PROTOCOL_GUID \
+  { \
+    0x9cf897ac, 0xc8cd, 0x4564, 0x8d, 0x8f, 0x1b, 0x88, 0xd4, 0xcf, 0xde, 0x22 \
+  }
+#define EFI_SMM_SPI_FLASH_UPDATE_PROTOCOL_GUID \
+  { \
+    0xc5922181, 0x7a76, 0x4777, 0x96, 0x85, 0x8a, 0xd3, 0x4e, 0xca, 0x0, 0x8c \
+  }
+#else
+#define EFI_SPI_FLASH_UPDATE_PROTOCOL_GUID \
+  { \
+    0x9cf897ac, 0xc8cd, 0x4564, \
+    { \
+      0x8d, 0x8f, 0x1b, 0x88, 0xd4, 0xcf, 0xde, 0x22 \
+    } \
+  }
+#define EFI_SMM_SPI_FLASH_UPDATE_PROTOCOL_GUID \
+  { \
+    0xc5922181, 0x7a76, 0x4777, \
+    { \
+      0x96, 0x85, 0x8a, 0xd3, 0x4e, 0xca, 0x0, 0x8c \
+    } \
+  }
+#endif
+
+//
+// Extern the GUID for protocol users.
+//
+extern EFI_GUID  gEfiSpiFlashUpdateProtocolGuid;
+extern EFI_GUID  gEfiSmmSpiFlashUpdateProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _EFI_SPI_FLASH_UPDATE_PROTOCOL EFI_SPI_FLASH_UPDATE_PROTOCOL;
+
+//
+// SMM SPI Flash Update protocol structure is the same as SPI Flash Update
+// protocol. The SMM one is intend to run in SMM environment.
+//
+typedef EFI_SPI_FLASH_UPDATE_PROTOCOL EFI_SMM_SPI_FLASH_UPDATE_PROTOCOL;
+
+//
+// Protocol member functions
+//
+
+/**
+  Read data from flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[out] Buffer                      Buffer contain the read data.
+
+  @retval EFI_SUCCESS                     Read successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_FLASH_UPDATE_FD_READ)(
+  IN  UINTN            FlashAddress,
+  IN  UINTN            NumBytes,
+  OUT VOID             *Buffer
+  );
+
+/**
+  Erase flash region according to input in a block size.
+
+  @param[in] FlashAddress                 Physical flash address.
+  @param[in] NumBytes                     Number in Byte, a block size in flash device.
+
+  @retval EFI_SUCCESS                     Erase successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_FLASH_UPDATE_FD_ERASE)(
+  IN  UINTN       FlashAddress,
+  IN  UINTN       NumBytes
+  );
+
+/**
+  Write data to flash device.
+
+  Write Buffer(FlashAddress|NumBytes) to flash device.
+
+  @param[in]  FlashAddress                Physical flash address.
+  @param[in]  NumBytes                    Number in Byte.
+  @param[in]  Buffer                      Buffer contain the write data.
+
+  @retval EFI_SUCCESS                     Write successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+  @retval others                          Some error occurs when executing this routine.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_FLASH_UPDATE_FD_Write)(
+  IN  UINTN           FlashAddress,
+  IN  UINTN           NumBytes,
+  IN  UINT8           *Buffer
+  );
+
+/**
+  Get flash device size and flash block size.
+
+  @param[out] FlashSize                   Pointer to the size of flash device.
+  @param[out] BlockSize                   Pointer to the size of block in flash device.
+
+  @retval EFI_SUCCESS                     Get successfully.
+  @retval EFI_INVALID_PARAMETER           Invalid parameter.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SPI_FLASH_GET_FLASH_SIZE_BLOCK_SIZE)(
+  OUT  UINTN            *FlashSize,
+  OUT  UINTN            *BlockSize
+  );
+
+//
+// Protocol definition
+//
+struct _EFI_SPI_FLASH_UPDATE_PROTOCOL {
+  EFI_SPI_FLASH_UPDATE_FD_READ               Read;
+  EFI_SPI_FLASH_UPDATE_FD_ERASE              Erase;
+  EFI_SPI_FLASH_UPDATE_FD_Write              Write;
+  EFI_SPI_FLASH_GET_FLASH_SIZE_BLOCK_SIZE    GetFlashSizeBlockSize;
+};
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
new file mode 100644
index 0000000000..61c5983c44
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
@@ -0,0 +1,528 @@
+/** @file
+  Implements PlatformFlashAccessLib.c
+  Platform Flash Access library.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/Spi.h>
+#include <Protocol/SpiCommon.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PrintLib.h>
+
+#define BLOCK_SIZE  0x1000
+
+//
+// Prefix Opcode Index on the host SPI controller
+//
+typedef enum {
+  SPI_WREN,             // Prefix Opcode 0: Write Enable
+  SPI_EWSR,             // Prefix Opcode 1: Enable Write Status Register
+} PREFIX_OPCODE_INDEX;
+
+STATIC EFI_PHYSICAL_ADDRESS  mInternalFdAddress;
+
+EFI_SPI_PROTOCOL  *mSpiProtocol;
+
+/**
+  Read NumBytes bytes of data from the address specified by
+  PAddress into Buffer.
+
+  @param[in]      Address       The starting physical address of the read.
+  @param[in,out]  NumBytes      On input, the number of bytes to read. On output, the number
+                                of bytes actually read.
+  @param[out]     Buffer        The destination data buffer for the read.
+
+  @retval         EFI_SUCCESS       Opertion is successful.
+  @retval         EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashRead (
+  IN     UINTN   Address,
+  IN OUT UINT32  *NumBytes,
+  OUT UINT8      *Buffer
+  )
+{
+  CopyMem (Buffer, (VOID *)Address, *NumBytes);
+  return EFI_SUCCESS;
+}
+
+/**
+  Write NumBytes bytes of data from Buffer to the address specified by
+  PAddresss.
+
+  @param[in]      Address         The starting physical address of the write.
+  @param[in,out]  NumBytes        On input, the number of bytes to write. On output,
+                                  the actual number of bytes written.
+  @param[in]      Buffer          The source data buffer for the write.
+
+  @retval         EFI_SUCCESS       Opertion is successful.
+  @retval         EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashWrite (
+  IN     UINTN   Address,
+  IN OUT UINT32  *NumBytes,
+  IN     UINT8   *Buffer
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Offset;
+  UINT32      Length;
+  UINT32      RemainingBytes;
+
+  ASSERT ((NumBytes != NULL) && (Buffer != NULL));
+  ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashAreaBaseAddress));
+
+  Offset = Address - (UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+  ASSERT ((*NumBytes + Offset) <= (UINTN)(PcdGet32 (PcdFlashAreaSize)*2));
+  Status         = EFI_SUCCESS;
+  RemainingBytes = *NumBytes;
+
+  while (RemainingBytes > 0) {
+    if (RemainingBytes > SIZE_4KB) {
+      Length = SIZE_4KB;
+    } else {
+      Length = RemainingBytes;
+    }
+
+    Status = mSpiProtocol->Execute (
+                             mSpiProtocol,
+                             SPI_OPCODE_WRITE_INDEX,
+                             SPI_WREN,
+                             TRUE,
+                             TRUE,
+                             TRUE,
+                             (UINT32)Offset,
+                             Length,
+                             Buffer,
+                             EnumSpiRegionAll
+                             );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    RemainingBytes -= Length;
+    Offset         += Length;
+    Buffer         += Length;
+  }
+
+  //
+  // Actual number of bytes written
+  //
+  *NumBytes -= RemainingBytes;
+
+  return Status;
+}
+
+/**
+  Read the block starting at Address.
+
+  @param[in]      BaseAddress         The starting physical address of the block to be read.
+  @param[in,out]  ReadBuffer          The pointer to a system memory buffer receiving the data read.
+
+  @return         The status returned from SpiFlashRead().
+
+**/
+EFI_STATUS
+InternalReadBlock (
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
+  OUT VOID                  *ReadBuffer
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      BlockSize;
+
+  BlockSize = BLOCK_SIZE;
+
+  Status = SpiFlashRead ((UINTN)BaseAddress, &BlockSize, ReadBuffer);
+
+  return Status;
+}
+
+/**
+  Erase the block starting at Address.
+
+  @param[in]  Address         The starting physical address of the block to be erased.
+                              This library assume that caller garantee that the PAddress
+                              is at the starting address of this block.
+  @param[in]  NumBytes        On input, the number of bytes of the logical block to be erased.
+                              On output, the actual number of bytes erased.
+
+  @retval     EFI_SUCCESS.      Opertion is successful.
+  @retval     EFI_DEVICE_ERROR  If there is any device errors.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiFlashBlockErase (
+  IN UINTN  Address,
+  IN UINTN  *NumBytes
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Offset;
+  UINTN       RemainingBytes;
+
+  ASSERT (NumBytes != NULL);
+  ASSERT (Address >= (UINTN)PcdGet32 (PcdFlashAreaBaseAddress));
+
+  Offset = Address - (UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+
+  ASSERT ((*NumBytes % SIZE_4KB) == 0);
+  // -  ASSERT ((*NumBytes + Offset) <= (UINTN)PcdGet32 (PcdFlashAreaSize));
+  ASSERT ((*NumBytes + Offset) <= (UINTN)(PcdGet32 (PcdFlashAreaSize)*2));
+  Status         = EFI_SUCCESS;
+  RemainingBytes = *NumBytes;
+
+  while (RemainingBytes > 0) {
+    Status = mSpiProtocol->Execute (
+                             mSpiProtocol,
+                             SPI_OPCODE_ERASE_INDEX,
+                             SPI_WREN,
+                             FALSE,
+                             TRUE,
+                             TRUE,
+                             (UINT32)Offset,
+                             0,
+                             NULL,
+                             EnumSpiRegionAll
+                             );
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    RemainingBytes -= SIZE_4KB;
+    Offset         += SIZE_4KB;
+  }
+
+  //
+  // Actual number of bytes erased
+  //
+  *NumBytes -= RemainingBytes;
+
+  return Status;
+}
+
+/**
+  Erase the whole block.
+
+  @param[in]  BaseAddress    Base address of the block to be erased.
+
+  @retval  EFI_SUCCESS   The command completed successfully.
+  @retval  Other         Device error or wirte-locked, operation failed.
+
+**/
+EFI_STATUS
+InternalEraseBlock (
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       NumBytes;
+
+  NumBytes = BLOCK_SIZE;
+
+  Status = SpiFlashBlockErase ((UINTN)BaseAddress, &NumBytes);
+
+  return Status;
+}
+
+/**
+  Compare the block value with buggfer.
+
+  @param[in]  BaseAddress    Base address of the block to be compare.
+  @param[in]  Buffer         The buffer to be compare.
+
+  @retval  EFI_SUCCESS                  The command compare successfully.
+  @retval  EFI_OUT_OF_RESOURCES         The resource has run out..
+
+**/
+EFI_STATUS
+InternalCompareBlock (
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN  UINT8                 *Buffer
+  )
+{
+  EFI_STATUS  Status;
+  VOID        *CompareBuffer;
+  UINT32      NumBytes;
+  INTN        CompareResult;
+
+  NumBytes      = BLOCK_SIZE;
+  CompareBuffer = AllocatePool (NumBytes);
+  if (CompareBuffer == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Done;
+  }
+
+  Status = SpiFlashRead ((UINTN)BaseAddress, &NumBytes, CompareBuffer);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  CompareResult = CompareMem (CompareBuffer, Buffer, BLOCK_SIZE);
+  if (CompareResult != 0) {
+    Status = EFI_VOLUME_CORRUPTED;
+  }
+
+Done:
+  if (CompareBuffer != NULL) {
+    FreePool (CompareBuffer);
+  }
+
+  return Status;
+}
+
+/**
+  Write a block of data.
+
+  @param[in]  BaseAddress    Base address of the block.
+  @param[in]  Buffer         Data buffer.
+  @param[in]  BufferSize     Size of the buffer.
+
+  @retval  EFI_SUCCESS             The command completed successfully.
+  @retval  EFI_INVALID_PARAMETER   Invalid parameter, can not proceed.
+  @retval  Other                   Device error or wirte-locked, operation failed.
+
+**/
+EFI_STATUS
+InternalWriteBlock (
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN  UINT8                 *Buffer,
+  IN  UINT32                BufferSize
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = SpiFlashWrite ((UINTN)BaseAddress, &BufferSize, Buffer);
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "\nFlash write error."));
+    return Status;
+  }
+
+  WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)BaseAddress, BLOCK_SIZE);
+
+  Status = InternalCompareBlock (BaseAddress, Buffer);
+  Status = EFI_SUCCESS;
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "\nError when writing to BaseAddress %x with different at offset %x.\n", BaseAddress, Status));
+  } else {
+    DEBUG ((DEBUG_INFO, "\nVerified data written to Block at %x is correct.\n", BaseAddress));
+  }
+
+  return Status;
+}
+
+/**
+  Perform flash write operation with progress indicator.  The start and end
+  completion percentage values are passed into this function.  If the requested
+  flash write operation is broken up, then completion percentage between the
+  start and end values may be passed to the provided Progress function.  The
+  caller of this function is required to call the Progress function for the
+  start and end completion percentage values.  This allows the Progress,
+  StartPercentage, and EndPercentage parameters to be ignored if the requested
+  flash write operation can not be broken up
+
+  @param[in] FirmwareType      The type of firmware.
+  @param[in] FlashAddress      The address of flash device to be accessed.
+  @param[in] FlashAddressType  The type of flash device address.
+  @param[in] Buffer            The pointer to the data buffer.
+  @param[in] Length            The length of data buffer in bytes.
+  @param[in] Progress          A function used report the progress of the
+                               firmware update.  This is an optional parameter
+                               that may be NULL.
+  @param[in] StartPercentage   The start completion percentage value that may
+                               be used to report progress during the flash
+                               write operation.
+  @param[in] EndPercentage     The end completion percentage value that may
+                               be used to report progress during the flash
+                               write operation.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWriteWithProgress (
+  IN PLATFORM_FIRMWARE_TYPE FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS FlashAddress,
+  IN FLASH_ADDRESS_TYPE FlashAddressType,
+  IN VOID *Buffer,
+  IN UINTN Length,
+  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL
+  IN UINTN                                          StartPercentage,
+  IN UINTN                                          EndPercentage
+  )
+{
+  EFI_STATUS            Status = EFI_SUCCESS;
+  UINTN                 Index;
+  EFI_PHYSICAL_ADDRESS  Address;
+  UINTN                 CountOfBlocks;
+  EFI_TPL               OldTpl;
+  BOOLEAN               FlashError;
+  UINT8                 *Buf;
+
+  Index         = 0;
+  Address       = 0;
+  CountOfBlocks = 0;
+  FlashError    = FALSE;
+  Buf           = Buffer;
+
+  DEBUG ((DEBUG_INFO | DEBUG_ERROR, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));
+  if (FlashAddressType == FlashAddressTypeRelativeAddress) {
+    FlashAddress = FlashAddress + mInternalFdAddress;
+  }
+
+  CountOfBlocks = (UINTN)(Length / BLOCK_SIZE);
+  Address       = FlashAddress;
+
+  //
+  // Raise TPL to TPL_NOTIFY to block any event handler,
+  // while still allowing RaiseTPL(TPL_NOTIFY) within
+  // output driver during Print()
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+  for (Index = 0; Index < CountOfBlocks; Index++) {
+    if (Progress != NULL) {
+      Progress (StartPercentage + ((Index * (EndPercentage - StartPercentage)) / CountOfBlocks));
+    }
+
+    //
+    // Handle block based on address and contents.
+    //
+    if (!EFI_ERROR (InternalCompareBlock (Address, Buf))) {
+      DEBUG ((DEBUG_INFO, "Skipping block at 0x%lx (already programmed)\n", Address));
+    } else {
+      //
+      // Make updating process uninterruptable,
+      // so that the flash memory area is not accessed by other entities
+      // which may interfere with the updating process
+      //
+      Status = InternalEraseBlock (Address);
+      if (EFI_ERROR (Status)) {
+        gBS->RestoreTPL (OldTpl);
+        FlashError = TRUE;
+        goto Done;
+      }
+
+      Status = InternalWriteBlock (
+                 Address,
+                 Buf,
+                 (UINT32)(Length > BLOCK_SIZE ? BLOCK_SIZE : Length)
+                 );
+      if (EFI_ERROR (Status)) {
+        gBS->RestoreTPL (OldTpl);
+        FlashError = TRUE;
+        goto Done;
+      }
+    }
+
+    //
+    // Move to next block to update.
+    //
+    Address += BLOCK_SIZE;
+    Buf     += BLOCK_SIZE;
+    if (Length > BLOCK_SIZE) {
+      Length -= BLOCK_SIZE;
+    } else {
+      Length = 0;
+    }
+  }
+
+  gBS->RestoreTPL (OldTpl);
+
+Done:
+
+  if (Progress != NULL) {
+    Progress (EndPercentage);
+  }
+
+  (VOID)FlashError;
+  return Status;
+}
+
+/**
+  Perform flash write operation.
+
+  @param[in] FirmwareType      The type of firmware.
+  @param[in] FlashAddress      The address of flash device to be accessed.
+  @param[in] FlashAddressType  The type of flash device address.
+  @param[in] Buffer            The pointer to the data buffer.
+  @param[in] Length            The length of data buffer in bytes.
+
+  @retval EFI_SUCCESS           The operation returns successfully.
+  @retval EFI_WRITE_PROTECTED   The flash device is read only.
+  @retval EFI_UNSUPPORTED       The flash device access is unsupported.
+  @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashWrite (
+  IN PLATFORM_FIRMWARE_TYPE  FirmwareType,
+  IN EFI_PHYSICAL_ADDRESS    FlashAddress,
+  IN FLASH_ADDRESS_TYPE      FlashAddressType,
+  IN VOID                    *Buffer,
+  IN UINTN                   Length
+  )
+{
+  return PerformFlashWriteWithProgress (
+           FirmwareType,
+           FlashAddress,
+           FlashAddressType,
+           Buffer,
+           Length,
+           NULL,
+           0,
+           0
+           );
+}
+
+/**
+  Platform Flash Access Lib Constructor.
+**/
+EFI_STATUS
+EFIAPI
+PerformFlashAccessLibConstructor (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  mInternalFdAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdFlashAreaBaseAddress);
+  DEBUG ((DEBUG_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));
+
+  Status = gBS->LocateProtocol (
+                  &gEfiSpiProtocolGuid,
+                  NULL,
+                  (VOID **)&mSpiProtocol
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
new file mode 100644
index 0000000000..6dc967efcd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
@@ -0,0 +1,52 @@
+## @file
+#  Platform Flash AccessLib
+#  Platform Flash Access library.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformFlashAccessLib
+  FILE_GUID                      = 31CF9CEC-DA4E-4505-AA20-33364A291A95
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformFlashAccessLib
+  CONSTRUCTOR                    = PerformFlashAccessLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  PlatformFlashAccessLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SignedCapsulePkg/SignedCapsulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  IoLib
+  PcdLib
+  DebugLib
+  MemoryAllocationLib
+  CacheMaintenanceLib
+
+[Guids]
+  gEdkiiSystemFmpCapsuleConfigFileGuid          ## SOMETIMES_CONSUMES ## GUID
+
+[Protocols]
+  gEfiSpiProtocolGuid                          ## CONSUMES
+
+[Pcd]
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress  ## SOMETIMES_CONSUMES
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize         ## SOMETIMES_CONSUMES
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114589): https://edk2.groups.io/g/devel/message/114589
Mute This Topic: https://groups.io/mt/103975454/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 14/32] AMD/VanGoghBoard: Check in SmbiosLib
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (12 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 15/32] AMD/VanGoghBoard: Check in SpiFlashDeviceLib Zhai, MingXin (Duke) via groups.io
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Provides library functions for common SMBIOS operations. Only available to DXE
  and UEFI module types.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Include/Library/SmbiosLib.h               | 171 ++++++++++
 .../Library/SmbiosLib/SmbiosLib.c             | 322 ++++++++++++++++++
 .../Library/SmbiosLib/SmbiosLib.inf           |  41 +++
 3 files changed, 534 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SmbiosLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.inf

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SmbiosLib.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SmbiosLib.h
new file mode 100644
index 0000000000..53e8652686
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/Library/SmbiosLib.h
@@ -0,0 +1,171 @@
+/** @file
+  Implements AMD SmbiosLib.h
+  Provides library functions for common SMBIOS operations. Only available to DXE
+  and UEFI module types.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2012, Apple Inc. All rights reserved. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SMBIOS_LIB_H_
+#define SMBIOS_LIB_H_
+
+#include <IndustryStandard/SmBios.h>
+#include <Protocol/Smbios.h>
+
+///
+/// Cache copy of the SMBIOS Protocol pointer
+///
+extern EFI_SMBIOS_PROTOCOL  *gSmbios;
+
+///
+/// Template for SMBIOS table initialization.
+/// The SMBIOS_TABLE_STRING types in the formated area must match the
+/// StringArray sequene.
+///
+typedef struct {
+  //
+  // formatted area of a given SMBIOS record
+  //
+  SMBIOS_STRUCTURE    *Entry;
+  //
+  // NULL terminated array of ASCII strings to be added to the SMBIOS record.
+  //
+  CHAR8               **StringArray;
+} SMBIOS_TEMPLATE_ENTRY;
+
+/**
+  Create an initial SMBIOS Table from an array of SMBIOS_TEMPLATE_ENTRY
+  entries. SMBIOS_TEMPLATE_ENTRY.NULL indicates the end of the table.
+
+  @param[in]  Template   Array of SMBIOS_TEMPLATE_ENTRY entries.
+
+  @retval EFI_SUCCESS          New SMBIOS tables were created.
+  @retval EFI_OUT_OF_RESOURCES New SMBIOS tables were not created.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibInitializeFromTemplate (
+  IN  SMBIOS_TEMPLATE_ENTRY  *Template
+  );
+
+/**
+  Create SMBIOS record.
+
+  Converts a fixed SMBIOS structure and an array of pointers to strings into
+  an SMBIOS record where the strings are cat'ed on the end of the fixed record
+  and terminated via a double NULL and add to SMBIOS table.
+
+  @param[in]  SmbiosEntry   Fixed SMBIOS structure
+  @param[in]  StringArray   Array of strings to convert to an SMBIOS string pack.
+                            NULL is OK.
+
+  @retval EFI_SUCCESS          New SmbiosEntry was added to SMBIOS table.
+  @retval EFI_OUT_OF_RESOURCES SmbiosEntry was not added.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibCreateEntry (
+  IN  SMBIOS_STRUCTURE  *SmbiosEntry,
+  IN  CHAR8             **StringArray
+  );
+
+/**
+  Update the string associated with an existing SMBIOS record.
+
+  This function allows the update of specific SMBIOS strings. The number of valid strings for any
+  SMBIOS record is defined by how many strings were present when Add() was called.
+
+  @param[in]    SmbiosHandle    SMBIOS Handle of structure that will have its string updated.
+  @param[in]    StringNumber    The non-zero string number of the string to update.
+  @param[in]    String          Update the StringNumber string with String.
+
+  @retval EFI_SUCCESS           SmbiosHandle had its StringNumber String updated.
+  @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. Or String is invalid.
+  @retval EFI_UNSUPPORTED       String was not added because it is longer than the SMBIOS Table supports.
+  @retval EFI_NOT_FOUND         The StringNumber.is not valid for this SMBIOS record.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibUpdateString (
+  IN  EFI_SMBIOS_HANDLE    SmbiosHandle,
+  IN  SMBIOS_TABLE_STRING  StringNumber,
+  IN  CHAR8                *String
+  );
+
+/**
+  Update the string associated with an existing SMBIOS record.
+
+  This function allows the update of specific SMBIOS strings. The number of valid strings for any
+  SMBIOS record is defined by how many strings were present when Add() was called.
+
+  @param[in]    SmbiosHandle    SMBIOS Handle of structure that will have its string updated.
+  @param[in]    StringNumber    The non-zero string number of the string to update.
+  @param[in]    String          Update the StringNumber string with String.
+
+  @retval EFI_SUCCESS           SmbiosHandle had its StringNumber String updated.
+  @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. Or String is invalid.
+  @retval EFI_UNSUPPORTED       String was not added because it is longer than the SMBIOS Table supports.
+  @retval EFI_NOT_FOUND         The StringNumber.is not valid for this SMBIOS record.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibUpdateUnicodeString (
+  IN  EFI_SMBIOS_HANDLE    SmbiosHandle,
+  IN  SMBIOS_TABLE_STRING  StringNumber,
+  IN  CHAR16               *String
+  );
+
+/**
+  Allow caller to read a specific SMBIOS string
+
+  @param[in]    Header          SMBIOS record that contains the string.
+  @param[in[    StringNumber    Instance of SMBIOS string 1 - N.
+
+  @retval NULL                  Instance of Type SMBIOS string was not found.
+  @retval Other                 Pointer to matching SMBIOS string.
+**/
+CHAR8 *
+EFIAPI
+SmbiosLibReadString (
+  IN SMBIOS_STRUCTURE   *Header,
+  IN EFI_SMBIOS_STRING  StringNumber
+  );
+
+/**
+  Allow the caller to discover a specific SMBIOS entry, and patch it if necissary.
+
+  @param[in]    Type            Type of the next SMBIOS record to return.
+  @param[in[    Instance        Instance of SMBIOS record 0 - N-1.
+  @param[out]   SmbiosHandle    Returns SMBIOS handle for the matching record.
+
+  @retval NULL                  Instance of Type SMBIOS record was not found.
+  @retval Other                 Pointer to matching SMBIOS record.
+**/
+SMBIOS_STRUCTURE *
+EFIAPI
+SmbiosLibGetRecord (
+  IN  EFI_SMBIOS_TYPE    Type,
+  IN  UINTN              Instance,
+  OUT EFI_SMBIOS_HANDLE  *SmbiosHandle
+  );
+
+/**
+  Remove an SMBIOS record.
+
+  This function removes an SMBIOS record using the handle specified by SmbiosHandle.
+
+  @param[in]    SmbiosHandle        The handle of the SMBIOS record to remove.
+
+  @retval EFI_SUCCESS               SMBIOS record was removed.
+  @retval EFI_INVALID_PARAMETER     SmbiosHandle does not specify a valid SMBIOS record.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibRemove (
+  OUT EFI_SMBIOS_HANDLE  SmbiosHandle
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.c
new file mode 100644
index 0000000000..52d5e2d131
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.c
@@ -0,0 +1,322 @@
+/** @file
+  Provides library functions for common SMBIOS operations. Only available to DXE
+  and UEFI module types.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2012, Apple Inc. All rights reserved.
+Portitions Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/SmbiosLib.h>
+
+EFI_SMBIOS_PROTOCOL  *gSmbios = NULL;
+
+/**
+  Create an initial SMBIOS Table from an array of SMBIOS_TEMPLATE_ENTRY
+  entries. SMBIOS_TEMPLATE_ENTRY.NULL indicates the end of the table.
+
+  @param[in]  Template   Array of SMBIOS_TEMPLATE_ENTRY entries.
+
+  @retval EFI_SUCCESS          New SMBIOS tables were created.
+  @retval EFI_OUT_OF_RESOURCES New SMBIOS tables were not created.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibInitializeFromTemplate (
+  IN  SMBIOS_TEMPLATE_ENTRY  *Template
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Index;
+
+  if (Template == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = EFI_SUCCESS;
+
+  for (Index = 0; Template[Index].Entry != NULL; Index++) {
+    Status = SmbiosLibCreateEntry (Template[Index].Entry, Template[Index].StringArray);
+  }
+
+  return Status;
+}
+
+/**
+  Create SMBIOS record.
+
+  @param[in]  SmbiosEntry   Fixed SMBIOS structure
+  @param[in]  StringArray   Array of strings to convert to an SMBIOS string pack.
+                        NULL is OK.
+
+  @return Return the status form gSmbios->Add.
+  @retval EFI_OUT_OF_RESOURCES New SMBIOS tables were not created.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibCreateEntry (
+  IN  SMBIOS_STRUCTURE  *SmbiosEntry,
+  IN  CHAR8             **StringArray
+  )
+{
+  EFI_STATUS               Status;
+  EFI_SMBIOS_HANDLE        SmbiosHandle;
+  EFI_SMBIOS_TABLE_HEADER  *Record;
+  UINTN                    Index;
+  UINTN                    StringSize;
+  UINTN                    Size;
+  CHAR8                    *Str;
+
+  // Calculate the size of the fixed record and optional string pack
+  Size = SmbiosEntry->Length;
+  if (StringArray == NULL) {
+    Size += 2; // Min string section is double null
+  } else if (StringArray[0] == NULL) {
+    Size += 2; // Min string section is double null
+  } else {
+    for (Index = 0; StringArray[Index] != NULL; Index++) {
+      StringSize = AsciiStrSize (StringArray[Index]);
+      Size      += StringSize;
+    }
+
+    // Don't forget the terminating double null
+    Size += 1;
+  }
+
+  // Copy over Template
+  Record = (EFI_SMBIOS_TABLE_HEADER *)AllocateZeroPool (Size);
+  if (Record == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (Record, SmbiosEntry, SmbiosEntry->Length);
+
+  if (StringArray != NULL) {
+    // Append string pack
+    Str = ((CHAR8 *)Record) + Record->Length;
+    for (Index = 0; StringArray[Index] != NULL; Index++) {
+      StringSize = AsciiStrSize (StringArray[Index]);
+      CopyMem (Str, StringArray[Index], StringSize);
+      Str += StringSize;
+    }
+
+    *Str = 0;
+  }
+
+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+  Status       = gSmbios->Add (
+                            gSmbios,
+                            gImageHandle,
+                            &SmbiosHandle,
+                            Record
+                            );
+
+  FreePool (Record);
+  return Status;
+}
+
+/**
+  Update the string associated with an existing SMBIOS record.
+
+  This function allows the update of specific SMBIOS strings. The number of valid strings for any
+  SMBIOS record is defined by how many strings were present when Add() was called.
+
+  @param[in]    SmbiosHandle    SMBIOS Handle of structure that will have its string updated.
+  @param[in]    StringNumber    The non-zero string number of the string to update.
+  @param[in]    String          Update the StringNumber string with String.
+
+  @retval EFI_SUCCESS           SmbiosHandle had its StringNumber String updated.
+  @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. Or String is invalid.
+  @retval EFI_UNSUPPORTED       String was not added because it is longer than the SMBIOS Table supports.
+  @retval EFI_NOT_FOUND         The StringNumber.is not valid for this SMBIOS record.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibUpdateString (
+  IN  EFI_SMBIOS_HANDLE    SmbiosHandle,
+  IN  SMBIOS_TABLE_STRING  StringNumber,
+  IN  CHAR8                *String
+  )
+{
+  UINTN  StringIndex;
+
+  if (String == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*String == '\0') {
+    // A string with no data is not legal in SMBIOS
+    return EFI_INVALID_PARAMETER;
+  }
+
+  StringIndex = StringNumber;
+  return gSmbios->UpdateString (gSmbios, &SmbiosHandle, &StringIndex, String);
+}
+
+/**
+  Update the string associated with an existing SMBIOS record.
+
+  This function allows the update of specific SMBIOS strings. The number of valid strings for any
+  SMBIOS record is defined by how many strings were present when Add() was called.
+
+  @param[in]    SmbiosHandle    SMBIOS Handle of structure that will have its string updated.
+  @param[in]    StringNumber    The non-zero string number of the string to update.
+  @param[in]    String          Update the StringNumber string with String.
+
+  @retval EFI_SUCCESS           SmbiosHandle had its StringNumber String updated.
+  @retval EFI_INVALID_PARAMETER SmbiosHandle does not exist. Or String is invalid.
+  @retval EFI_UNSUPPORTED       String was not added because it is longer than the SMBIOS Table supports.
+  @retval EFI_NOT_FOUND         The StringNumber.is not valid for this SMBIOS record.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibUpdateUnicodeString (
+  IN  EFI_SMBIOS_HANDLE    SmbiosHandle,
+  IN  SMBIOS_TABLE_STRING  StringNumber,
+  IN  CHAR16               *String
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       StringIndex;
+  CHAR8       *Ascii;
+
+  if (String == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*String == '\0') {
+    // A string with no data is not legal in SMBIOS
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Ascii = AllocateZeroPool (StrSize (String));
+  if (Ascii == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  UnicodeStrToAsciiStrS (String, Ascii, StrSize (String));
+
+  StringIndex = StringNumber;
+  Status      = gSmbios->UpdateString (gSmbios, &SmbiosHandle, &StringIndex, Ascii);
+
+  FreePool (Ascii);
+  return Status;
+}
+
+/**
+  Allow caller to read a specific SMBIOS string
+
+  @param[in]    Header          SMBIOS record that contains the string.
+  @param[in[    StringNumber    Instance of SMBIOS string 1 - N.
+
+  @retval NULL                  Instance of Type SMBIOS string was not found.
+  @retval Other                 Pointer to matching SMBIOS string.
+**/
+CHAR8 *
+EFIAPI
+SmbiosLibReadString (
+  IN SMBIOS_STRUCTURE   *Header,
+  IN EFI_SMBIOS_STRING  StringNumber
+  )
+{
+  CHAR8  *Data;
+  UINTN  Match;
+
+  Data = (CHAR8 *)Header + Header->Length;
+  for (Match = 1; !(*Data == 0 && *(Data+1) == 0); ) {
+    if (StringNumber == Match) {
+      return Data;
+    }
+
+    Data++;
+    if (*(Data - 1) == '\0') {
+      Match++;
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Allow the caller to discover a specific SMBIOS entry, and patch it if necissary.
+
+  @param[in]    Type            Type of the next SMBIOS record to return.
+  @param[in[    Instance        Instance of SMBIOS record 0 - N-1.
+  @param[out]   SmbiosHandle    Returns SMBIOS handle for the matching record.
+
+  @retval NULL                  Instance of Type SMBIOS record was not found.
+  @retval Other                 Pointer to matching SMBIOS record.
+**/
+SMBIOS_STRUCTURE *
+EFIAPI
+SmbiosLibGetRecord (
+  IN  EFI_SMBIOS_TYPE    Type,
+  IN  UINTN              Instance,
+  OUT EFI_SMBIOS_HANDLE  *SmbiosHandle
+  )
+{
+  EFI_STATUS               Status;
+  EFI_SMBIOS_TABLE_HEADER  *Record;
+  UINTN                    Match;
+
+  Match         = 0;
+  *SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+  do {
+    Status = gSmbios->GetNext (gSmbios, SmbiosHandle, &Type, &Record, NULL);
+    if (!EFI_ERROR (Status)) {
+      if (Match == Instance) {
+        return (SMBIOS_STRUCTURE *)Record;
+      }
+
+      Match++;
+    }
+  } while (!EFI_ERROR (Status));
+
+  return NULL;
+}
+
+/**
+  Remove an SMBIOS record.
+
+  This function removes an SMBIOS record using the handle specified by SmbiosHandle.
+
+  @param[in]    SmbiosHandle        The handle of the SMBIOS record to remove.
+
+  @retval EFI_SUCCESS               SMBIOS record was removed.
+  @retval EFI_INVALID_PARAMETER     SmbiosHandle does not specify a valid SMBIOS record.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibRemove (
+  OUT EFI_SMBIOS_HANDLE  SmbiosHandle
+  )
+{
+  return gSmbios->Remove (gSmbios, SmbiosHandle);
+}
+
+/**
+
+  @param[in]  ImageHandle  ImageHandle of the loaded driver.
+  @param[in]  SystemTable  Pointer to the EFI System Table.
+
+  @retval  EFI_SUCCESS            Register successfully.
+  @retval  EFI_OUT_OF_RESOURCES   No enough memory to register this handler.
+**/
+EFI_STATUS
+EFIAPI
+SmbiosLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  return gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&gSmbios);
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.inf
new file mode 100644
index 0000000000..c1829d6f2d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SmbiosLib/SmbiosLib.inf
@@ -0,0 +1,41 @@
+# SMBIOS Library
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2012, Apple Inc. All rights reserved.
+# Portions copyright (c) 2006 - 2010, Intel Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmbiosLib
+  FILE_GUID                      = 56E8FB13-C554-F864-E3D1-9A0EAC76F867
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SmbiosLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER SMM_CORE UEFI_APPLICATION UEFI_DRIVER
+
+  CONSTRUCTOR                    = SmbiosLibConstructor
+
+
+[Sources]
+  SmbiosLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiLib
+
+[Protocols]
+  gEfiSmbiosProtocolGuid
+
+[Depex]
+  gEfiSmbiosProtocolGuid
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114590): https://edk2.groups.io/g/devel/message/114590
Mute This Topic: https://groups.io/mt/103975456/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 15/32] AMD/VanGoghBoard: Check in SpiFlashDeviceLib
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (13 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 14/32] AMD/VanGoghBoard: Check in SmbiosLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 16/32] AMD/VanGoghBoard: Check in BaseTscTimerLib Zhai, MingXin (Duke) via groups.io
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial AMD SpiFlashDeviceLib for Chachani board flash IC.
  Chachani board use the W25Q256JW as flash IC.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../SpiFlashDeviceLib/SpiFlashDeviceLib.c     | 42 +++++++++++++++++++
 .../SpiFlashDeviceLib/SpiFlashDeviceLib.inf   | 29 +++++++++++++
 2 files changed, 71 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.inf

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.c
new file mode 100644
index 0000000000..49636f6a89
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.c
@@ -0,0 +1,42 @@
+/** @file
+  Implements SpiFlashDeviceLib.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/SpiFlashDeviceLib.h>
+
+SPI_INIT_TABLE  mSpiInitTable[] = {
+  { // W25Q256JW/W74M25JW
+    SF_VENDOR_ID_WINBOND,
+    SF_DEVICE_ID0_W25Q256JW,
+    SF_DEVICE_ID1_W25Q256JW,
+    {
+      SPI_COMMAND_WRITE_ENABLE,
+      SPI_COMMAND_WRITE_S_EN
+    },
+    {
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_JEDEC_ID,          EnumSpiOperationJedecId            },
+      { EnumSpiOpcodeWriteNoAddr,SPI_COMMAND_WRITE_S,           EnumSpiOperationWriteStatus        },
+      { EnumSpiOpcodeWrite,    SPI_COMMAND_WRITE,             EnumSpiOperationProgramData_1_Byte },
+      { EnumSpiOpcodeRead,     SPI_COMMAND_READ,              EnumSpiOperationReadData           },
+      { EnumSpiOpcodeWrite,    SPI_COMMAND_ERASE,             EnumSpiOperationErase_4K_Byte      },
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_READ_S,            EnumSpiOperationReadStatus         },
+      { EnumSpiOpcodeWriteNoAddr,SPI_COMMAND_CHIP_ERASE,        EnumSpiOperationFullChipErase      },
+      { EnumSpiOpcodeRead,     SPI_COMMAND_READ_SFDP,         EnumSpiOperationReadData           },
+      { EnumSpiOpcodeWriteNoAddr,SPI_COMMAND_RPMC_OP1,          EnumSpiOperationOther              },
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_RPMC_OP2,          EnumSpiOperationReadData           },
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_Enter_4Byte_Addr,  EnumSpiOperationOther              },
+      { EnumSpiOpcodeReadNoAddr,SPI_COMMAND_Exit_4Byte_Addr,   EnumSpiOperationOther              }
+    },
+    0,
+    0x2000000   // BIOS image size in flash
+  }
+};
+
+//
+// The total number of support flash part
+//
+UINT8  mNumSpiFlashMax = sizeof (mSpiInitTable) / sizeof (mSpiInitTable[0]);
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.inf
new file mode 100644
index 0000000000..951cf6c480
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/SpiFlashDeviceLib/SpiFlashDeviceLib.inf
@@ -0,0 +1,29 @@
+## @file
+# SpiFlashDeviceLib
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SpiFlashDeviceLib
+  FILE_GUID                      = D5A903A8-4D19-4E4C-AAF4-07C5D10D5939
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = SpiFlashDeviceLib
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  SpiFlashDeviceLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+
+[LibraryClasses]
+  SpiFlashDeviceLib
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114591): https://edk2.groups.io/g/devel/message/114591
Mute This Topic: https://groups.io/mt/103975457/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 16/32] AMD/VanGoghBoard: Check in BaseTscTimerLib
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (14 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 15/32] AMD/VanGoghBoard: Check in SpiFlashDeviceLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 17/32] AMD/VanGoghBoard: Check in Smm access module Zhai, MingXin (Duke) via groups.io
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Provides basic TSC timer calibration based on the ACPI timer hardware.
  The performance counter features are provided by the processors time stamp counter.

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>
---
 .../Library/TscTimerLib/BaseTscTimerLib.c     |  23 ++
 .../Library/TscTimerLib/BaseTscTimerLib.inf   |  43 +++
 .../Library/TscTimerLib/DxeTscTimerLib.c      |  80 ++++++
 .../Library/TscTimerLib/DxeTscTimerLib.inf    |  55 ++++
 .../Library/TscTimerLib/PeiTscTimerLib.c      |  53 ++++
 .../Library/TscTimerLib/PeiTscTimerLib.inf    |  49 ++++
 .../Library/TscTimerLib/TscTimerLibInternal.h |  53 ++++
 .../Library/TscTimerLib/TscTimerLibShare.c    | 255 ++++++++++++++++++
 8 files changed, 611 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c
new file mode 100644
index 0000000000..7dfef490e9
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.c
@@ -0,0 +1,23 @@
+/** @file
+  ACPI Timer implements one instance of Timer Library.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TscTimerLibInternal.h"
+
+/**  Get TSC frequency.
+
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+InternalGetTscFrequency (
+  VOID
+  )
+{
+  return InternalCalculateTscFrequency ();
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf
new file mode 100644
index 0000000000..d6c4e2e1d6
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/BaseTscTimerLib.inf
@@ -0,0 +1,43 @@
+## @file
+# BaseTscTimerLib
+#  Provides basic timer support using the ACPI timer hardware.  The performance
+#  counter features are provided by the processors time stamp counter.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseTscTimerLib
+  FILE_GUID                      = D29338B9-50FE-4e4f-B7D4-A150A2C1F4FB
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib
+
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources.common]
+  TscTimerLibShare.c
+  BaseTscTimerLib.c
+  TscTimerLibInternal.h
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  AgesaPublic/AgesaPublic.dec
+
+
+[LibraryClasses]
+  PcdLib
+  PciLib
+  IoLib
+  BaseLib
+
+[Pcd.common]
+  gEfiAmdAgesaPkgTokenSpaceGuid.PcdAmdFchCfgAcpiPmTmrBlkAddr
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c
new file mode 100644
index 0000000000..5a374665c3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.c
@@ -0,0 +1,80 @@
+/** @file
+  ACPI Timer implements one instance of Timer Library.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) Microsoft Corporation.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include "TscTimerLibInternal.h"
+
+UINT64  mTscFrequency;
+
+/** The constructor function determines the actual TSC frequency.
+
+  First, Get TSC frequency from system configuration table with TSC frequency GUID,
+  if the table is not found, install it.
+  This function will always return EFI_SUCCESS.
+
+  @param  ImageHandle       The firmware allocated handle for the EFI image.
+  @param  SystemTable       A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeTscTimerLibConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      *TscFrequency;
+
+  TscFrequency = NULL;
+  //
+  // Get TSC frequency from system configuration table with TSC frequency GUID.
+  //
+  Status = EfiGetSystemConfigurationTable (&gAmdCommonPkgTscFrequencyGuid, (VOID **)&TscFrequency);
+  if (Status == EFI_SUCCESS) {
+    ASSERT (TscFrequency != NULL);
+    mTscFrequency = *TscFrequency;
+    return EFI_SUCCESS;
+  }
+
+  //
+  // TSC frequency GUID system configuration table is not found, install it.
+  //
+
+  Status = gBS->AllocatePool (EfiBootServicesData, sizeof (UINT64), (VOID **)&TscFrequency);
+  ASSERT_EFI_ERROR (Status);
+
+  *TscFrequency = InternalCalculateTscFrequency ();
+  //
+  // TscFrequency now points to the number of TSC counts per second, install system configuration table for it.
+  //
+  gBS->InstallConfigurationTable (&gAmdCommonPkgTscFrequencyGuid, TscFrequency);
+
+  mTscFrequency = *TscFrequency;
+  return EFI_SUCCESS;
+}
+
+/**  Get TSC frequency.
+
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+InternalGetTscFrequency (
+  VOID
+  )
+{
+  return mTscFrequency;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf
new file mode 100644
index 0000000000..a9caae59a5
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf
@@ -0,0 +1,55 @@
+## @file
+#  DXE ACPI Timer Library
+#
+#  Provides basic timer support using the ACPI timer hardware.  The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Note: The implementation uses the lower 24-bits of the ACPI timer and
+#  is compatible with both 24-bit and 32-bit ACPI timers.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeTscTimerLib
+  FILE_GUID                      = 95ab030f-b4fd-4ee4-92a5-9e04e87634d9
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE
+
+  CONSTRUCTOR                    = DxeTscTimerLibConstructor
+
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources.common]
+  TscTimerLibShare.c
+  DxeTscTimerLib.c
+  TscTimerLibInternal.h
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  PcdLib
+  PciLib
+  IoLib
+  BaseLib
+  UefiLib
+  DebugLib
+
+[Guids]
+  gAmdCommonPkgTscFrequencyGuid                          ## CONSUMES ## System Configuration Table
+
+[Pcd.common]
+  gEfiAmdAgesaPkgTokenSpaceGuid.PcdAmdFchCfgAcpiPmTmrBlkAddr
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c
new file mode 100644
index 0000000000..338821b5d7
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.c
@@ -0,0 +1,53 @@
+/** @file
+  ACPI Timer implements one instance of Timer Library.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/HobLib.h>
+#include "TscTimerLibInternal.h"
+
+/**  Get TSC frequency from TSC frequency GUID HOB, if the HOB is not found, build it.
+
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+InternalGetTscFrequency (
+  VOID
+  )
+{
+  EFI_HOB_GUID_TYPE  *GuidHob;
+  VOID               *DataInHob;
+  UINT64             TscFrequency;
+
+  //
+  // Get TSC frequency from TSC frequency GUID HOB.
+  //
+  GuidHob = GetFirstGuidHob (&gAmdCommonPkgTscFrequencyGuid);
+  if (GuidHob != NULL) {
+    DataInHob    = GET_GUID_HOB_DATA (GuidHob);
+    TscFrequency = *(UINT64 *)DataInHob;
+    return TscFrequency;
+  }
+
+  //
+  // TSC frequency GUID HOB is not found, build it.
+  //
+
+  TscFrequency = InternalCalculateTscFrequency ();
+  //
+  // TscFrequency is now equal to the number of TSC counts per second, build GUID HOB for it.
+  //
+  BuildGuidDataHob (
+    &gAmdCommonPkgTscFrequencyGuid,
+    &TscFrequency,
+    sizeof (UINT64)
+    );
+
+  return TscFrequency;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf
new file mode 100644
index 0000000000..0af33ada5f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf
@@ -0,0 +1,49 @@
+## @file
+#  PEI ACPI Timer Library
+#
+#  Provides basic timer support using the ACPI timer hardware.  The performance
+#  counter features are provided by the processors time stamp counter.
+#
+#  Note: The implementation uses the lower 24-bits of the ACPI timer and
+#  is compatible with both 24-bit and 32-bit ACPI timers.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiTscTimerLib
+  FILE_GUID                      = 342C36C0-15DF-43b4-9EC9-FBF748BFB3D1
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TimerLib|PEIM PEI_CORE
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources.common]
+  TscTimerLibShare.c
+  PeiTscTimerLib.c
+  TscTimerLibInternal.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  AgesaPublic/AgesaPublic.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+
+[LibraryClasses]
+  PcdLib
+  PciLib
+  IoLib
+  BaseLib
+  HobLib
+
+[Guids]
+  gAmdCommonPkgTscFrequencyGuid                          ## PRODUCES ## HOB
+
+[Pcd.common]
+  gEfiAmdAgesaPkgTokenSpaceGuid.PcdAmdFchCfgAcpiPmTmrBlkAddr
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h
new file mode 100644
index 0000000000..619100ef0e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibInternal.h
@@ -0,0 +1,53 @@
+/** @file
+  Header file internal to ACPI TimerLib.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef TSC_TIMER_LIB_INTERNAL_H_
+#define TSC_TIMER_LIB_INTERNAL_H_
+
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+
+#include <Library/IoLib.h>
+#define ACPI_MMIO_BASE   0xFED80000ul
+#define PMIO_BASE        0x300  // DWORD
+#define FCH_PMIOA_REG64  0x64   // AcpiPmTmrBlk
+
+/**  Get TSC frequency.
+
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+InternalGetTscFrequency (
+  VOID
+  );
+
+/**  Calculate TSC frequency.
+
+  The TSC counting frequency is determined by comparing how far it counts
+  during a 1ms period as determined by the ACPI timer. The ACPI timer is
+  used because it counts at a known frequency.
+  If ACPI I/O space not enabled, this function will enable it. Then the
+  TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms.
+  The TSC is then sampled again. The difference multiplied by 1000 is the TSC
+  frequency. There will be a small error because of the overhead of reading
+  the ACPI timer. An attempt is made to determine and compensate for this error.
+
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+InternalCalculateTscFrequency (
+  VOID
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c
new file mode 100644
index 0000000000..a49a2db2b3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/TscTimerLibShare.c
@@ -0,0 +1,255 @@
+/** @file
+  ACPI Timer implements one instance of Timer Library.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TscTimerLibInternal.h"
+
+/**  Calculate TSC frequency.
+
+  The TSC counting frequency is determined by comparing how far it counts
+  during a 1ms period as determined by the ACPI timer. The ACPI timer is
+  used because it counts at a known frequency.
+  If ACPI I/O space not enabled, this function will enable it. Then the
+  TSC is sampled, followed by waiting for 3579 clocks of the ACPI timer, or 1ms.
+  The TSC is then sampled again. The difference multiplied by 1000 is the TSC
+  frequency. There will be a small error because of the overhead of reading
+  the ACPI timer. An attempt is made to determine and compensate for this error.
+
+  @return The number of TSC counts per second.
+
+**/
+UINT64
+InternalCalculateTscFrequency (
+  VOID
+  )
+{
+  UINT64  StartTSC;
+  UINT64  EndTSC;
+  UINT16  TimerAddr;
+  UINT32  Ticks;
+  UINT64  TscFrequency;
+
+  TimerAddr = MmioRead16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG64);
+  if (TimerAddr == 0) {
+    TimerAddr = PcdGet16 (PcdAmdFchCfgAcpiPmTmrBlkAddr);
+    MmioWrite16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG64, TimerAddr);
+  }
+
+  //
+  // ACPI I/O space should be enabled now, locate the ACPI Timer.
+  // ACPI I/O base address maybe have be initialized by other driver with different value,
+  // So get it from PCI space directly.
+  //
+  Ticks    = IoRead32 (TimerAddr) + (3579);   // Set Ticks to 1ms in the future
+  StartTSC = AsmReadTsc ();                   // Get base value for the TSC
+  //
+  // Wait until the ACPI timer has counted 1ms.
+  // Timer wrap-arounds are handled correctly by this function.
+  // When the current ACPI timer value is greater than 'Ticks', the while loop will exit.
+  //
+  while (((Ticks - IoRead32 (TimerAddr)) & BIT23) == 0) {
+    CpuPause ();
+  }
+
+  EndTSC = AsmReadTsc ();    // TSC value 1ms later
+
+  TscFrequency =   MultU64x32 (
+                     (EndTSC - StartTSC),     // Number of TSC counts in 1ms
+                     1000                     // Number of ms in a second
+                     );
+
+  return TscFrequency;
+}
+
+/**  Stalls the CPU for at least the given number of ticks.
+
+  Stalls the CPU for at least the given number of ticks. It's invoked by
+  MicroSecondDelay() and NanoSecondDelay().
+
+  @param[in]  Delay     A period of time to delay in ticks.
+
+**/
+VOID
+InternalX86Delay (
+  IN      UINT64  Delay
+  )
+{
+  UINT64  Ticks;
+
+  //
+  // The target timer count is calculated here
+  //
+  Ticks = AsmReadTsc () + Delay;
+
+  //
+  // Wait until time out
+  // Timer wrap-arounds are NOT handled correctly by this function.
+  // Thus, this function must be called within 10 years of reset since
+  // Intel ensures a minimum of 10 years before the TSC wraps.
+  //
+  while (AsmReadTsc () <= Ticks) {
+    CpuPause ();
+  }
+}
+
+/**  Stalls the CPU for at least the specified number of MicroSeconds.
+
+  @param[in]  MicroSeconds  The minimum number of microseconds to delay.
+
+  @return The value of MicroSeconds input.
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+  IN      UINTN  MicroSeconds
+  )
+{
+  InternalX86Delay (
+    DivU64x32 (
+      MultU64x64 (
+        InternalGetTscFrequency (),
+        MicroSeconds
+        ),
+      1000000u
+      )
+    );
+  return MicroSeconds;
+}
+
+/**  Stalls the CPU for at least the specified number of NanoSeconds.
+
+  @param[in]  NanoSeconds The minimum number of nanoseconds to delay.
+
+  @return The value of NanoSeconds input.
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+  IN      UINTN  NanoSeconds
+  )
+{
+  InternalX86Delay (
+    DivU64x32 (
+      MultU64x32 (
+        InternalGetTscFrequency (),
+        (UINT32)NanoSeconds
+        ),
+      1000000000u
+      )
+    );
+  return NanoSeconds;
+}
+
+/**  Retrieves the current value of the 64-bit free running Time-Stamp counter.
+
+  The time-stamp counter (as implemented in the P6 family, Pentium, Pentium M,
+  Pentium 4, Intel Xeon, Intel Core Solo and Intel Core Duo processors and
+  later processors) is a 64-bit counter that is set to 0 following a RESET of
+  the processor.  Following a RESET, the counter increments even when the
+  processor is halted by the HLT instruction or the external STPCLK# pin. Note
+  that the assertion of the external DPSLP# pin may cause the time-stamp
+  counter to stop.
+
+  The properties of the counter can be retrieved by the
+  GetPerformanceCounterProperties() function.
+
+  @return The current value of the free running performance counter.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounter (
+  VOID
+  )
+{
+  return AsmReadTsc ();
+}
+
+/**  Retrieves the 64-bit frequency in Hz and the range of performance counter
+  values.
+
+  If StartValue is not NULL, then the value that the performance counter starts
+  with, 0x0, is returned in StartValue. If EndValue is not NULL, then the value
+  that the performance counter end with, 0xFFFFFFFFFFFFFFFF, is returned in
+  EndValue.
+
+  The 64-bit frequency of the performance counter, in Hz, is always returned.
+  To determine average processor clock frequency, Intel recommends the use of
+  EMON logic to count processor core clocks over the period of time for which
+  the average is required.
+
+
+  @param[out]   StartValue  Pointer to where the performance counter's starting value is saved, or NULL.
+  @param[out]   EndValue    Pointer to where the performance counter's ending value is saved, or NULL.
+
+  @return The frequency in Hz.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounterProperties (
+  OUT      UINT64 *StartValue, OPTIONAL
+  OUT      UINT64                    *EndValue     OPTIONAL
+  )
+{
+  if (StartValue != NULL) {
+    *StartValue = 0;
+  }
+
+  if (EndValue != NULL) {
+    *EndValue = 0xFFFFFFFFFFFFFFFFull;
+  }
+
+  return InternalGetTscFrequency ();
+}
+
+/**
+  Converts elapsed ticks of performance counter to time in nanoseconds.
+
+  This function converts the elapsed ticks of running performance counter to
+  time value in unit of nanoseconds.
+
+  @param  Ticks     The number of elapsed ticks of running performance counter.
+
+  @return The elapsed time in nanoseconds.
+
+**/
+UINT64
+EFIAPI
+GetTimeInNanoSecond (
+  IN      UINT64  Ticks
+  )
+{
+  UINT64  Frequency;
+  UINT64  NanoSeconds;
+  UINT64  Remainder;
+  INTN    Shift;
+
+  Frequency = GetPerformanceCounterProperties (NULL, NULL);
+
+  //
+  //          Ticks
+  // Time = --------- x 1,000,000,000
+  //        Frequency
+  //
+  NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
+
+  //
+  // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
+  // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
+  // i.e. highest bit set in Remainder should <= 33.
+  //
+  Shift        = MAX (0, HighBitSet64 (Remainder) - 33);
+  Remainder    = RShiftU64 (Remainder, (UINTN)Shift);
+  Frequency    = RShiftU64 (Frequency, (UINTN)Shift);
+  NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
+
+  return NanoSeconds;
+}
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114592): https://edk2.groups.io/g/devel/message/114592
Mute This Topic: https://groups.io/mt/103975466/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 17/32] AMD/VanGoghBoard: Check in Smm access module
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (15 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 16/32] AMD/VanGoghBoard: Check in BaseTscTimerLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 18/32] AMD/VanGoghBoard: Check in PciHostBridge module Zhai, MingXin (Duke) via groups.io
                   ` (15 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial AMD Smm access module.
  Contains description files for ACPI SMM Platform handler module.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Smm/AcpiSmm/AcpiSmmPlatform.c             | 183 ++++++++
 .../Smm/AcpiSmm/AcpiSmmPlatform.h             |  50 ++
 .../Smm/AcpiSmm/AcpiSmmPlatform.inf           |  57 +++
 .../Smm/SmmAccessPei/SmmAccessPei.c           | 436 ++++++++++++++++++
 .../Smm/SmmAccessPei/SmmAccessPei.inf         |  43 ++
 5 files changed, 769 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.h
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.inf
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.c
 create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.inf

diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.c
new file mode 100644
index 0000000000..20a0ed6cb7
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.c
@@ -0,0 +1,183 @@
+/** @file
+ACPISMM Driver implementation file.
+
+This is QNC Smm platform driver
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2019 Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <AcpiSmmPlatform.h>
+
+/**
+  Allocate EfiACPIMemoryNVS below 4G memory address.
+
+  This function allocates EfiACPIMemoryNVS below 4G memory address.
+
+  @param[in] Size   Size of memory to allocate.
+
+  @return       Allocated address for output.
+
+**/
+VOID *
+AllocateAcpiNvsMemoryBelow4G (
+  IN UINTN  Size
+  )
+{
+  UINTN                 Pages;
+  EFI_PHYSICAL_ADDRESS  Address;
+  EFI_STATUS            Status;
+  VOID                  *Buffer;
+
+  Pages   = EFI_SIZE_TO_PAGES (Size);
+  Address = 0xffffffff;
+
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  EfiACPIMemoryNVS,
+                  Pages,
+                  &Address
+                  );
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  Buffer = (VOID *)(UINTN)Address;
+  ZeroMem (Buffer, Size);
+
+  return Buffer;
+}
+
+/**
+  Reserved S3 memory for InstallS3Memory
+
+  @retval  EFI_OUT_OF_RESOURCES     Insufficient resources to complete function.
+  @retval  EFI_SUCCESS              Function has completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+ReservedS3Memory (
+  UINTN  SystemMemoryLength
+
+  )
+
+{
+  VOID                            *GuidHob;
+  EFI_SMRAM_HOB_DESCRIPTOR_BLOCK  *DescriptorBlock;
+  VOID                            *AcpiReservedBase;
+
+  UINTN                   TsegIndex;
+  UINTN                   TsegSize;
+  UINTN                   TsegBase;
+  RESERVED_ACPI_S3_RANGE  *AcpiS3Range;
+
+  DEBUG ((DEBUG_INFO, "ReservedS3Memory, SystemMemoryLength: 0x%08X\n", SystemMemoryLength));
+  //
+  // Get Hob list for SMRAM desc
+  //
+  GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
+  ASSERT (GuidHob != NULL);
+  DEBUG ((DEBUG_INFO, "gEfiSmmPeiSmramMemoryReserveGuid: 0x%X \n", (UINTN)GuidHob));
+  DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+  ASSERT (DescriptorBlock != NULL);
+
+  //
+  // Use the hob to get SMRAM capabilities
+  //
+  TsegIndex = DescriptorBlock->NumberOfSmmReservedRegions - 1;
+  DEBUG ((DEBUG_INFO, "DescriptorBlock->NumberOfSmmReservedRegions: 0x%X\n", DescriptorBlock->NumberOfSmmReservedRegions));
+  DEBUG ((DEBUG_INFO, "TsegIndex: 0x%X\n", TsegIndex));
+  ASSERT (TsegIndex <= (MAX_SMRAM_RANGES - 1));
+  TsegBase = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalStart;
+  TsegSize = (UINTN)DescriptorBlock->Descriptor[TsegIndex].PhysicalSize;
+
+  DEBUG ((DEBUG_INFO, "SMM  Base: %08X\n", TsegBase));
+  DEBUG ((DEBUG_INFO, "SMM  Size: %08X\n", TsegSize));
+
+  //
+  // Now find the location of the data structure that is used to store the address
+  // of the S3 reserved memory.
+  //
+  AcpiS3Range = (RESERVED_ACPI_S3_RANGE *)(UINTN)(TsegBase + RESERVED_ACPI_S3_RANGE_OFFSET);
+  DEBUG ((DEBUG_INFO, "AcpiS3Range: %08X\n", (UINTN)AcpiS3Range));
+  //
+  // Allocate reserved ACPI memory for S3 resume.  Pointer to this region is
+  // stored in SMRAM in the first page of TSEG.
+  //
+  AcpiReservedBase = AllocateAcpiNvsMemoryBelow4G (PcdGet32 (PcdS3AcpiReservedMemorySize));
+  DEBUG ((DEBUG_INFO, "AcpiReservedBase: %08X\n", (UINTN)AcpiReservedBase));
+  ASSERT (AcpiReservedBase != NULL);
+  if (AcpiReservedBase != NULL) {
+    AcpiS3Range->AcpiReservedMemoryBase = (UINT32)(UINTN)AcpiReservedBase;
+    AcpiS3Range->AcpiReservedMemorySize = PcdGet32 (PcdS3AcpiReservedMemorySize);
+  }
+
+  AcpiS3Range->SystemMemoryLength = (UINT32)SystemMemoryLength;
+
+  DEBUG ((DEBUG_INFO, "S3 Memory  Base:    %08X\n", AcpiS3Range->AcpiReservedMemoryBase));
+  DEBUG ((DEBUG_INFO, "S3 Memory  Size:    %08X\n", AcpiS3Range->AcpiReservedMemorySize));
+  DEBUG ((DEBUG_INFO, "S3 SysMemoryLength: %08X\n", AcpiS3Range->SystemMemoryLength));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Initializes the SMM S3 Handler Driver.
+
+  @param[in]  ImageHandle     The image handle of Sleep State Wake driver.
+  @param[in]  SystemTable     The starndard EFI system table.
+
+  @retval  EFI_OUT_OF_RESOURCES     Insufficient resources to complete function.
+  @retval  EFI_SUCCESS              Function has completed successfully.
+  @retval  Other                    Error occured during execution.
+
+**/
+EFI_STATUS
+EFIAPI
+InitAcpiSmmPlatform (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+
+{
+  EFI_STATUS                    Status;
+  EFI_GLOBAL_NVS_AREA_PROTOCOL  *AcpiNvsProtocol = NULL;
+  UINTN                         MemoryLength;
+  EFI_PEI_HOB_POINTERS          Hob;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiGlobalNvsAreaProtocolGuid,
+                  NULL,
+                  (VOID **)&AcpiNvsProtocol
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Calculate the system memory length by memory hobs
+  //
+  MemoryLength = 0x100000;
+  Hob.Raw      = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
+  ASSERT (Hob.Raw != NULL);
+  while ((Hob.Raw != NULL) && (!END_OF_HOB_LIST (Hob))) {
+    if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+      //
+      // Skip the memory region below 1MB
+      //
+      if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) {
+        MemoryLength += (UINTN)Hob.ResourceDescriptor->ResourceLength;
+      }
+    }
+
+    Hob.Raw = GET_NEXT_HOB (Hob);
+    Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
+  }
+
+  Status = ReservedS3Memory (MemoryLength);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.h
new file mode 100644
index 0000000000..31ab4f083d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.h
@@ -0,0 +1,50 @@
+/** @file
+Header file for SMM S3 Handler Driver.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2019 Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef ACPI_SMM_DRIVER_H_
+#define ACPI_SMM_DRIVER_H_
+//
+// Include files
+//
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/GlobalNvsArea.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/S3IoLib.h>
+#include <Library/S3BootScriptLib.h>
+#include <Guid/Acpi.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Library/HobLib.h>
+
+//
+// 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))
+#define MAX_SMRAM_RANGES               4
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.inf
new file mode 100644
index 0000000000..428e04b7d2
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/AcpiSmm/AcpiSmmPlatform.inf
@@ -0,0 +1,57 @@
+## @file
+# Component description file for ACPI SMM Platform handler module
+#
+# This is QNC Smm platform driver .
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013-2019 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+  INF_VERSION                 = 0x00010005
+  BASE_NAME                   = AcpiSmmPlatform
+  FILE_GUID                   = 833AF7CC-C58F-4BF6-8FCD-A46667F2BAD3
+  MODULE_TYPE                 = DXE_SMM_DRIVER
+  VERSION_STRING              = 1.0
+  PI_SPECIFICATION_VERSION    = 0x0001000A
+  ENTRY_POINT                 = InitAcpiSmmPlatform
+
+[Sources]
+  AcpiSmmPlatform.c
+  AcpiSmmPlatform.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  ReportStatusCodeLib
+  UefiDriverEntryPoint
+  DebugLib
+  IoLib
+  PciLib
+  BaseMemoryLib
+  BaseLib
+  SmmServicesTableLib
+  PcdLib
+  HobLib
+  S3BootScriptLib
+  LockBoxLib
+
+[Protocols]
+  gEfiGlobalNvsAreaProtocolGuid
+
+[Guids]
+  gEfiSmmPeiSmramMemoryReserveGuid
+
+[Pcd]
+  gPlatformPkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize
+
+[Depex]
+  gEfiGlobalNvsAreaProtocolGuid
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.c b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.c
new file mode 100644
index 0000000000..7880acc2f3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.c
@@ -0,0 +1,436 @@
+/** @file
+This is the driver that publishes the SMM Access Ppi
+instance for the Quark SOC.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2019 Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiPei.h>
+#include <Ppi/SmmAccess.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeiServicesLib.h>
+#include <AGESA.h>
+#define SMMMASK_ADDRESS  0xC0010113
+
+#define SMM_ACCESS_PRIVATE_DATA_FROM_THIS(a) \
+  CR ( \
+  a, \
+  SMM_ACCESS_PRIVATE_DATA, \
+  SmmAccess, \
+  SMM_ACCESS_PRIVATE_DATA_SIGNATURE \
+  )
+
+typedef struct {
+  UINTN                   Signature;
+  EFI_HANDLE              Handle;
+  PEI_SMM_ACCESS_PPI      SmmAccess;
+  UINTN                   NumberRegions;
+  EFI_SMRAM_DESCRIPTOR    *SmramDesc;
+} SMM_ACCESS_PRIVATE_DATA;
+
+#define SMM_ACCESS_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('4', '5', 's', 'a')
+
+/**
+  CpuOpenSMRAM - read/write A0000-BFFFF
+
+  @param         VOID                  None.
+
+  @retval        VOID                  None.
+**/
+VOID
+EFIAPI
+OpenSMRAM (
+  VOID
+  )
+{
+  volatile UINT64  RegValue;
+
+  // Disable protection in ASeg and TSeg
+  RegValue  = AsmReadMsr64 (SMMMASK_ADDRESS);
+  RegValue &= (UINT64)(~BIT0);
+  RegValue &= (UINT64)(~BIT1);
+  AsmWriteMsr64 (SMMMASK_ADDRESS, RegValue);
+
+  // Enable FixMtrrModEn
+  RegValue  = AsmReadMsr64 (SYS_CFG);
+  RegValue |= (UINT64)(1 << 19);
+  AsmWriteMsr64 (SYS_CFG, RegValue);
+
+  // Enable Rd/Wr DRAM in ASeg
+  RegValue  = AsmReadMsr64 (AMD_AP_MTRR_FIX16k_A0000);
+  RegValue |= 0x1010101010101010;
+  RegValue |= 0x0808080808080808;
+  AsmWriteMsr64 (AMD_AP_MTRR_FIX16k_A0000, RegValue);
+
+  // Disable FixMtrrModEn
+  RegValue  = AsmReadMsr64 (SYS_CFG);
+  RegValue &= ~(UINT64)(1 << 19);
+  AsmWriteMsr64 (SYS_CFG, RegValue);
+}
+
+/**
+  CpuSmramWP - write protect from A0000-BFFFF
+
+  @param         VOID                  None.
+
+  @retval        VOID                  None.
+**/
+VOID
+EFIAPI
+CloseSmram (
+  VOID
+  )
+{
+  volatile UINT64  RegValue;
+
+  // Enable FixMtrrModEn
+  RegValue  = AsmReadMsr64 (SYS_CFG);
+  RegValue |= (UINT64)(1 << 19);
+  AsmWriteMsr64 (SYS_CFG, RegValue);
+
+  // Disable Rd/Wr DRAM in ASeg
+  RegValue  = AsmReadMsr64 (AMD_AP_MTRR_FIX16k_A0000);
+  RegValue &= 0xEFEFEFEFEFEFEFEF;
+  RegValue &= 0xF7F7F7F7F7F7F7F7;
+  AsmWriteMsr64 (AMD_AP_MTRR_FIX16k_A0000, RegValue);
+
+  // Disable FixMtrrModEn
+  RegValue  = AsmReadMsr64 (SYS_CFG);
+  RegValue &= ~(UINT64)(1 << 19);
+  AsmWriteMsr64 (SYS_CFG, RegValue);
+
+  RegValue  = AsmReadMsr64 (SMMMASK_ADDRESS);
+  RegValue |= (UINT64)BIT0;
+  RegValue |= (UINT64)BIT1;
+  AsmWriteMsr64 (SMMMASK_ADDRESS, RegValue);
+}
+
+/**
+  Setting the bit0 of MSRC001_0015 Hardware Configuration (HWCR) to do SMM code lock.
+
+  @param         VOID                  None.
+
+  @retval        VOID                  None.
+**/
+VOID
+EFIAPI
+LockSmm (
+  VOID
+  )
+{
+  volatile UINT64  Data64;
+
+  Data64  = AsmReadMsr64 (HWCR);
+  Data64 |= (UINT64)BIT0; // SMM_LOCK
+  AsmWriteMsr64 (HWCR, Data64);
+}
+
+/**
+  This routine accepts a request to "open" a region of SMRAM.  The
+  region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
+  The use of "open" means that the memory is visible from all PEIM
+  and SMM agents.
+
+  @param[in]  PeiServices        General purpose services available to every PEIM.
+  @param[in]  This                Pointer to the SMM Access Interface.
+  @param[in]  DescriptorIndex     Region of SMRAM to Open.
+
+  @retval  EFI_SUCCESS               The region was successfully opened.
+  @retval  EFI_DEVICE_ERROR          The region could not be opened because locked by
+                                     chipset.
+  @retval  EFI_INVALID_PARAMETER     The descriptor index was out of bounds.
+
+**/
+EFI_STATUS
+EFIAPI
+Open (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_SMM_ACCESS_PPI  *This,
+  IN UINTN               DescriptorIndex
+  )
+{
+  SMM_ACCESS_PRIVATE_DATA  *SmmAccess;
+
+  SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+  if (DescriptorIndex >= SmmAccess->NumberRegions) {
+    DEBUG ((DEBUG_WARN, "SMRAM region out of range in Open\n"));
+    return EFI_INVALID_PARAMETER;
+  } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {
+    DEBUG ((DEBUG_WARN, "Cannot open a locked SMRAM region in Open\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Open TSEG
+  //
+  OpenSMRAM ();
+
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~(EFI_SMRAM_CLOSED | EFI_ALLOCATED);
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_OPEN;
+  SmmAccess->SmmAccess.OpenState                     = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine accepts a request to "close" a region of SMRAM.  This is valid for
+  compatible SMRAM region.
+
+  @param[in]  PeiServices        General purpose services available to every PEIM.
+  @param[in]  This                Pointer to the SMM Access Interface.
+  @param[in]  DescriptorIndex     Region of SMRAM to Close.
+
+  @retval  EFI_SUCCESS               The region was successfully closed.
+  @retval  EFI_DEVICE_ERROR          The region could not be closed because locked by
+                                     chipset.
+  @retval  EFI_INVALID_PARAMETER     The descriptor index was out of bounds.
+
+**/
+EFI_STATUS
+EFIAPI
+Close (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_SMM_ACCESS_PPI  *This,
+  IN UINTN               DescriptorIndex
+  )
+{
+  SMM_ACCESS_PRIVATE_DATA  *SmmAccess;
+  BOOLEAN                  OpenState;
+  UINT8                    Index;
+
+  SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+  if (DescriptorIndex >= SmmAccess->NumberRegions) {
+    DEBUG ((DEBUG_WARN, "SMRAM region out of range in Close\n"));
+    return EFI_INVALID_PARAMETER;
+  } else if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_LOCKED) {
+    DEBUG ((DEBUG_WARN, "SmmAccess Close region is locked:%d\n", DescriptorIndex));
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (SmmAccess->SmramDesc[DescriptorIndex].RegionState & EFI_SMRAM_CLOSED) {
+    DEBUG ((DEBUG_WARN, "SmmAccess Close region is closed already:%d\n", DescriptorIndex));
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Close TSEG
+  //
+  CloseSmram ();
+
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState &= ~EFI_SMRAM_OPEN;
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState |= (EFI_SMRAM_CLOSED | EFI_ALLOCATED);
+
+  //
+  // Find out if any regions are still open
+  //
+  OpenState = FALSE;
+  for (Index = 0; Index < SmmAccess->NumberRegions; Index++) {
+    if ((SmmAccess->SmramDesc[Index].RegionState & EFI_SMRAM_OPEN) == EFI_SMRAM_OPEN) {
+      OpenState = TRUE;
+    }
+  }
+
+  SmmAccess->SmmAccess.OpenState = OpenState;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine accepts a request to "lock" SMRAM.  The
+  region could be legacy AB or TSEG near top of physical memory.
+  The use of "lock" means that the memory can no longer be opened
+  to PEIM.
+
+  @param[in]  PeiServices        General purpose services available to every PEIM.
+  @param[in]  This                Pointer to the SMM Access Interface.
+  @param[in]  DescriptorIndex     Region of SMRAM to Lock.
+
+  @retval  EFI_SUCCESS               The region was successfully locked.
+  @retval  EFI_DEVICE_ERROR          The region could not be locked because at least
+                                     one range is still open.
+  @retval  EFI_INVALID_PARAMETER     The descriptor index was out of bounds.
+
+**/
+EFI_STATUS
+EFIAPI
+Lock (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_SMM_ACCESS_PPI  *This,
+  IN UINTN               DescriptorIndex
+  )
+{
+  SMM_ACCESS_PRIVATE_DATA  *SmmAccess;
+
+  SmmAccess = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+
+  if (DescriptorIndex >= SmmAccess->NumberRegions) {
+    DEBUG ((DEBUG_WARN, "SMRAM region out of range in Lock\n"));
+    return EFI_INVALID_PARAMETER;
+  } else if (SmmAccess->SmmAccess.OpenState) {
+    DEBUG ((DEBUG_WARN, "Cannot lock SMRAM when SMRAM regions are still open\n"));
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Lock TSEG
+  //
+  LockSmm ();
+  SmmAccess->SmramDesc[DescriptorIndex].RegionState |= EFI_SMRAM_LOCKED;
+  SmmAccess->SmmAccess.LockState                     = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine services a user request to discover the SMRAM
+  capabilities of this platform.  This will report the possible
+  ranges that are possible for SMRAM access, based upon the
+  memory controller capabilities.
+
+  @param[in]       PeiServices     General purpose services available to every PEIM.
+  @param[in]       This             Pointer to the SMRAM Access Interface.
+  @param[in, out]  SmramMapSize     Pointer to the variable containing size of the
+                                    buffer to contain the description information.
+  @param[in, out]  SmramMap         Buffer containing the data describing the Smram
+                                    region descriptors.
+
+  @retval  EFI_BUFFER_TOO_SMALL     The user did not provide a sufficient buffer.
+  @retval  EFI_SUCCESS              The user provided a sufficiently-sized buffer.
+
+**/
+EFI_STATUS
+EFIAPI
+GetCapabilities (
+  IN EFI_PEI_SERVICES          **PeiServices,
+  IN PEI_SMM_ACCESS_PPI        *This,
+  IN OUT UINTN                 *SmramMapSize,
+  IN OUT EFI_SMRAM_DESCRIPTOR  *SmramMap
+  )
+{
+  EFI_STATUS               Status;
+  SMM_ACCESS_PRIVATE_DATA  *SmmAccess;
+  UINTN                    BufferSize;
+
+  SmmAccess  = SMM_ACCESS_PRIVATE_DATA_FROM_THIS (This);
+  BufferSize = SmmAccess->NumberRegions * sizeof (EFI_SMRAM_DESCRIPTOR);
+
+  if (*SmramMapSize < BufferSize) {
+    DEBUG ((DEBUG_WARN, "SMRAM Map Buffer too small\n"));
+    Status = EFI_BUFFER_TOO_SMALL;
+  } else {
+    CopyMem (SmramMap, SmmAccess->SmramDesc, BufferSize);
+    Status = EFI_SUCCESS;
+  }
+
+  *SmramMapSize = BufferSize;
+
+  return Status;
+}
+
+/**
+  This is the constructor for the SMM Access Ppi
+
+  @param[in]    FfsHeader        FfsHeader.
+  @param[in]    PeiServices      General purpose services available to every PEIM.
+
+  @retval  EFI_SUCCESS       Protocol successfully started and installed.
+  @retval  EFI_UNSUPPORTED   Protocol can't be started.
+**/
+EFI_STATUS
+EFIAPI
+SmmAccessPeiEntryPoint (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_BOOT_MODE                   BootMode;
+  UINTN                           Index;
+  EFI_SMRAM_HOB_DESCRIPTOR_BLOCK  *DescriptorBlock = NULL;
+  SMM_ACCESS_PRIVATE_DATA         *SmmAccessPrivate;
+  EFI_PEI_PPI_DESCRIPTOR          *PpiList;
+  EFI_HOB_GUID_TYPE               *GuidHob;
+
+  Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);
+  if (EFI_ERROR (Status) || (BootMode != BOOT_ON_S3_RESUME)) {
+    //
+    // If not in S3 boot path. do nothing
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Initialize private data
+  //
+  SmmAccessPrivate = AllocateZeroPool (sizeof (*SmmAccessPrivate));
+  ASSERT (SmmAccessPrivate != NULL);
+
+  PpiList = AllocateZeroPool (sizeof (*PpiList));
+  ASSERT (PpiList != NULL);
+
+  //
+  // Build SMM related information
+  //
+  SmmAccessPrivate->Signature = SMM_ACCESS_PRIVATE_DATA_SIGNATURE;
+  SmmAccessPrivate->Handle    = NULL;
+
+  //
+  // Get Hob list
+  //
+  GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
+  ASSERT (GuidHob != NULL);
+  DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+  ASSERT (DescriptorBlock != NULL);
+
+  //
+  // Alloc space for SmmAccessPrivate->SmramDesc
+  //
+  SmmAccessPrivate->SmramDesc = AllocateZeroPool ((DescriptorBlock->NumberOfSmmReservedRegions) * sizeof (EFI_SMRAM_DESCRIPTOR));
+  if (SmmAccessPrivate->SmramDesc == NULL) {
+    DEBUG ((DEBUG_ERROR, "Alloc SmmAccessPrivate->SmramDesc fail.\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Use the hob to publish SMRAM capabilities
+  //
+  for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {
+    SmmAccessPrivate->SmramDesc[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;
+    SmmAccessPrivate->SmramDesc[Index].CpuStart      = DescriptorBlock->Descriptor[Index].CpuStart;
+    SmmAccessPrivate->SmramDesc[Index].PhysicalSize  = DescriptorBlock->Descriptor[Index].PhysicalSize;
+    SmmAccessPrivate->SmramDesc[Index].RegionState   = DescriptorBlock->Descriptor[Index].RegionState;
+  }
+
+  SmmAccessPrivate->NumberRegions             = Index;
+  SmmAccessPrivate->SmmAccess.Open            = Open;
+  SmmAccessPrivate->SmmAccess.Close           = Close;
+  SmmAccessPrivate->SmmAccess.Lock            = Lock;
+  SmmAccessPrivate->SmmAccess.GetCapabilities = GetCapabilities;
+  SmmAccessPrivate->SmmAccess.LockState       = FALSE;
+  SmmAccessPrivate->SmmAccess.OpenState       = FALSE;
+
+  PpiList->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+  PpiList->Guid  = &gPeiSmmAccessPpiGuid;
+  PpiList->Ppi   = &SmmAccessPrivate->SmmAccess;
+
+  Status = (**PeiServices).InstallPpi (PeiServices, PpiList);
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG (
+    (EFI_D_INFO, "SMM Base:Size %08X:%08X\n",
+     (UINTN)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalStart),
+     (UINTN)(SmmAccessPrivate->SmramDesc[SmmAccessPrivate->NumberRegions-1].PhysicalSize)
+    ));
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.inf b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.inf
new file mode 100644
index 0000000000..741eddd43c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Smm/SmmAccessPei/SmmAccessPei.inf
@@ -0,0 +1,43 @@
+## @file
+# Component description file for SmmAccessPei module
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013-2019 Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+INF_VERSION          = 0x00010005
+BASE_NAME            = SmmAccessPei
+FILE_GUID            = C6E6E43A-5DB1-4810-AAB7-C5A2A0914713
+MODULE_TYPE          = PEIM
+VERSION_STRING       = 1.0
+ENTRY_POINT          = SmmAccessPeiEntryPoint
+
+[Sources]
+  SmmAccessPei.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  PeimEntryPoint
+  PeiServicesLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  DebugLib
+  HobLib
+
+[Ppis]
+  gPeiSmmAccessPpiGuid                         # ALWAYS_PRODUCED
+
+[Guids]
+  gEfiSmmPeiSmramMemoryReserveGuid
+
+[Depex]
+  gEfiPeiMasterBootModePpiGuid AND gEfiPeiMemoryDiscoveredPpiGuid
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114593): https://edk2.groups.io/g/devel/message/114593
Mute This Topic: https://groups.io/mt/103975468/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 18/32] AMD/VanGoghBoard: Check in PciHostBridge module
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (16 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 17/32] AMD/VanGoghBoard: Check in Smm access module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 19/32] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module Zhai, MingXin (Duke) via groups.io
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial PciHostBridge module. Provides the basic interfaces to abstract
  a PCI Host Bridge Resource Allocation.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Bus/Pci/PciHostBridgeDxe/IoFifo.h         |  170 ++
 .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.c  | 1370 ++++++++++
 .../Bus/Pci/PciHostBridgeDxe/PciHostBridge.h  |  624 +++++
 .../Pci/PciHostBridgeDxe/PciHostBridge.uni    |  Bin 0 -> 1290 bytes
 .../Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf |   54 +
 .../PciHostBridgeDxe/PciHostBridgeExtra.uni   |  Bin 0 -> 826 bytes
 .../Pci/PciHostBridgeDxe/PciRootBridgeIo.c    | 2421 +++++++++++++++++
 7 files changed, 4639 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/IoFifo.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/IoFifo.h b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/IoFifo.h
new file mode 100644
index 0000000000..cd6ed34f22
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/IoFifo.h
@@ -0,0 +1,170 @@
+/** @file
+  Implementation of IoFifo.h
+  I/O FIFO routines
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef IO_FIFO_H_INCLUDED_
+#define IO_FIFO_H_INCLUDED_
+
+/**
+  Reads an 8-bit I/O port fifo into a block of memory.
+
+  Reads the 8-bit I/O fifo port specified by Port.
+
+  The port is read Count times, and the read data is
+  stored in the provided Buffer.
+
+  This function must guarantee that all I/O read and write operations are
+  serialized.
+
+  If 8-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to read.
+  @param  Count   The number of times to read I/O port.
+  @param  Buffer  The buffer to store the read data into.
+
+**/
+VOID
+EFIAPI
+IoReadFifo8 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Reads a 16-bit I/O port fifo into a block of memory.
+
+  Reads the 16-bit I/O fifo port specified by Port.
+
+  The port is read Count times, and the read data is
+  stored in the provided Buffer.
+
+  This function must guarantee that all I/O read and write operations are
+  serialized.
+
+  If 16-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to read.
+  @param  Count   The number of times to read I/O port.
+  @param  Buffer  The buffer to store the read data into.
+
+**/
+VOID
+EFIAPI
+IoReadFifo16 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Reads a 32-bit I/O port fifo into a block of memory.
+
+  Reads the 32-bit I/O fifo port specified by Port.
+
+  The port is read Count times, and the read data is
+  stored in the provided Buffer.
+
+  This function must guarantee that all I/O read and write operations are
+  serialized.
+
+  If 32-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to read.
+  @param  Count   The number of times to read I/O port.
+  @param  Buffer  The buffer to store the read data into.
+
+**/
+VOID
+EFIAPI
+IoReadFifo32 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Writes a block of memory into an 8-bit I/O port fifo.
+
+  Writes the 8-bit I/O fifo port specified by Port.
+
+  The port is written Count times, and the write data is
+  retrieved from the provided Buffer.
+
+  This function must guarantee that all I/O write and write operations are
+  serialized.
+
+  If 8-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to write.
+  @param  Count   The number of times to write I/O port.
+  @param  Buffer  The buffer to store the write data into.
+
+**/
+VOID
+EFIAPI
+IoWriteFifo8 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Writes a block of memory into a 16-bit I/O port fifo.
+
+  Writes the 16-bit I/O fifo port specified by Port.
+
+  The port is written Count times, and the write data is
+  retrieved from the provided Buffer.
+
+  This function must guarantee that all I/O write and write operations are
+  serialized.
+
+  If 16-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to write.
+  @param  Count   The number of times to write I/O port.
+  @param  Buffer  The buffer to store the write data into.
+
+**/
+VOID
+EFIAPI
+IoWriteFifo16 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+/**
+  Writes a block of memory into a 32-bit I/O port fifo.
+
+  Writes the 32-bit I/O fifo port specified by Port.
+
+  The port is written Count times, and the write data is
+  retrieved from the provided Buffer.
+
+  This function must guarantee that all I/O write and write operations are
+  serialized.
+
+  If 32-bit I/O port operations are not supported, then ASSERT().
+
+  @param  Port    The I/O port to write.
+  @param  Count   The number of times to write I/O port.
+  @param  Buffer  The buffer to store the write data into.
+
+**/
+VOID
+EFIAPI
+IoWriteFifo32 (
+  IN      UINTN  Port,
+  IN      UINTN  Count,
+  OUT     VOID   *Buffer
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
new file mode 100644
index 0000000000..6fc9b22b8f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
@@ -0,0 +1,1370 @@
+/** @file
+  Implementation of PciHostBridge.c
+  Provides the basic interfaces to abstract a PCI Host Bridge Resource
+  Allocation
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciHostBridge.h"
+#define TOP_MEM  0xC001001Aul
+
+//
+// Hard code: Root Bridge Number within the host bridge
+//            Root Bridge's attribute
+//            Root Bridge's device path
+//            Root Bridge's resource aperture
+//
+UINTN  RootBridgeNumber[1] = { 1 };
+
+UINT64  RootBridgeAttribute[1][1] = {
+  { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM }
+};
+
+EFI_PCI_ROOT_BRIDGE_DEVICE_PATH  mEfiPciRootBridgeDevicePath[1][1] = {
+  {
+    {
+      {
+        {
+          ACPI_DEVICE_PATH,
+          ACPI_DP,
+          {
+            (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),
+            (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
+          }
+        },
+        EISA_PNP_ID (0x0A03),
+        0
+      },
+
+      {
+        END_DEVICE_PATH_TYPE,
+        END_ENTIRE_DEVICE_PATH_SUBTYPE,
+        {
+          END_DEVICE_PATH_LENGTH,
+          0
+        }
+      }
+    }
+  }
+};
+
+PCI_ROOT_BRIDGE_RESOURCE_APERTURE  mResAperture[1][1] = {
+  {
+    { 0, 0xff, 0xE0000000, 0xffffffff, 0, 0xffff }
+  }
+};
+
+EFI_HANDLE  mDriverImageHandle;
+
+PCI_HOST_BRIDGE_INSTANCE  mPciHostBridgeInstanceTemplate = {
+  PCI_HOST_BRIDGE_SIGNATURE,  // Signature
+  NULL,                       // HostBridgeHandle
+  0,                          // RootBridgeNumber
+  { NULL, NULL },             // Head
+  FALSE,                      // ResourceSubiteed
+  TRUE,                       // CanRestarted
+  {
+    NotifyPhase,
+    GetNextRootBridge,
+    GetAttributes,
+    StartBusEnumeration,
+    SetBusNumbers,
+    SubmitResources,
+    GetProposedResources,
+    PreprocessController
+  }
+};
+
+//
+// Implementation
+//
+
+/**
+  Entry point of this driver
+
+  @param ImageHandle     Handle of driver image
+  @param SystemTable     Point to EFI_SYSTEM_TABLE
+
+  @retval EFI_OUT_OF_RESOURCES  Can not allocate memory resource
+  @retval EFI_DEVICE_ERROR      Can not install the protocol instance
+  @retval EFI_SUCCESS           Success to initialize the Pci host bridge.
+**/
+EFI_STATUS
+EFIAPI
+InitializePciHostBridge (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     Loop1;
+  UINTN                     Loop2;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridge;
+  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+  EFI_PHYSICAL_ADDRESS      TopOfLowMem;
+
+  mDriverImageHandle         = ImageHandle;
+  TopOfLowMem                = AsmReadMsr64 (TOP_MEM);
+  mResAperture[0][0].MemBase = TopOfLowMem;
+
+  //
+  // Create Host Bridge Device Handle
+  //
+  for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
+    HostBridge = AllocateCopyPool (
+                   sizeof (PCI_HOST_BRIDGE_INSTANCE),
+                   &mPciHostBridgeInstanceTemplate
+                   );
+    if (HostBridge == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
+    InitializeListHead (&HostBridge->Head);
+
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &HostBridge->HostBridgeHandle,
+                    &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+                    &HostBridge->ResAlloc,
+                    NULL
+                    );
+    if (EFI_ERROR (Status)) {
+      FreePool (HostBridge);
+      return EFI_DEVICE_ERROR;
+    }
+
+    //
+    // Create Root Bridge Device Handle in this Host Bridge
+    //
+
+    for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
+      PrivateData = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));
+      if (PrivateData == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      PrivateData->Signature  = PCI_ROOT_BRIDGE_SIGNATURE;
+      PrivateData->DevicePath =
+        (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];
+
+      RootBridgeConstructor (
+        &PrivateData->Io,
+        HostBridge->HostBridgeHandle,
+        RootBridgeAttribute[Loop1][Loop2],
+        &mResAperture[Loop1][Loop2]
+        );
+
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &PrivateData->Handle,
+                      &gEfiDevicePathProtocolGuid,
+                      PrivateData->DevicePath,
+                      &gEfiPciRootBridgeIoProtocolGuid,
+                      &PrivateData->Io,
+                      NULL
+                      );
+      if (EFI_ERROR (Status)) {
+        FreePool (PrivateData);
+        return EFI_DEVICE_ERROR;
+      }
+
+      InsertTailList (&HostBridge->Head, &PrivateData->Link);
+    }
+  }
+
+  Status = gDS->AddIoSpace (
+                  EfiGcdIoTypeIo,
+                  0x2000,
+                  0xFFFF-0x2000
+                  );
+  ASSERT_EFI_ERROR (Status);
+  TopOfLowMem = AsmReadMsr64 (TOP_MEM);
+  Status      = gDS->AddMemorySpace (
+                       EfiGcdMemoryTypeMemoryMappedIo,
+                       TopOfLowMem,
+                       0xF8000000-TopOfLowMem,
+                       0
+                       );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  These are the notifications from the PCI bus driver that it is about to enter
+  a certain phase of the PCI enumeration process.
+
+  This member function can be used to notify the host bridge driver to perform
+  specific actions, including any chipset-specific initialization, so that the
+  chipset is ready to enter the next phase. Eight notification points are
+  defined at this time. See belows:
+
+  EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures
+                                         and internal data structures. The PCI
+                                         enumerator should issue this
+                                         notification before starting a fresh
+                                         enumeration process. Enumeration
+                                         cannot be restarted after sending any
+                                         other notification such as
+                                         EfiPciHostBridgeBeginBusAllocation.
+
+  EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to
+                                         begin. No specific action is required
+                                         here. This notification can be used to
+                                         perform any chipset-specific
+                                         programming.
+
+  EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming
+                                         phase is complete. No specific action
+                                         is required here. This notification
+                                         can be used to perform any
+                                         chipset-specific programming.
+
+  EfiPciHostBridgeBeginResourceAllocation
+                                         The resource allocation phase is about
+                                         to begin. No specific action is
+                                         required here. This notification can
+                                         be used to perform any
+                                         chipset-specific programming.
+
+  EfiPciHostBridgeAllocateResources      Allocates resources per previously
+                                         submitted requests for all the PCI
+                                         root bridges. These resource settings
+                                         are returned on the next call to
+                                         GetProposedResources(). Before calling
+                                         NotifyPhase() with a Phase of
+                                         EfiPciHostBridgeAllocateResource, the
+                                         PCI bus enumerator is responsible for
+                                         gathering I/O and memory requests for
+                                         all the PCI root bridges and
+                                         submitting these requests using
+                                         SubmitResources(). This function pads
+                                         the resource amount to suit the root
+                                         bridge hardware, takes care of
+                                         dependencies between the PCI root
+                                         bridges, and calls the Global
+                                         Coherency Domain (GCD) with the
+                                         allocation request. In the case of
+                                         padding, the allocated range could be
+                                         bigger than what was requested.
+
+  EfiPciHostBridgeSetResources           Programs the host bridge hardware to
+                                         decode previously allocated resources
+                                         (proposed resources) for all the PCI
+                                         root bridges. After the hardware is
+                                         programmed, reassigning resources will
+                                         not be supported. The bus settings are
+                                         not affected.
+
+  EfiPciHostBridgeFreeResources          Deallocates resources that were
+                                         previously allocated for all the PCI
+                                         root bridges and resets the I/O and
+                                         memory apertures to their initial
+                                         state. The bus settings are not
+                                         affected. If the request to allocate
+                                         resources fails, the PCI enumerator
+                                         can use this notification to
+                                         deallocate previous resources, adjust
+                                         the requests, and retry allocation.
+
+  EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is
+                                         completed. No specific action is
+                                         required here. This notification can
+                                         be used to perform any chipsetspecific
+                                         programming.
+
+  @param[in] This                The instance pointer of
+                                 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+  @param[in] Phase               The phase during enumeration
+
+  @retval EFI_NOT_READY          This phase cannot be entered at this time. For
+                                 example, this error is valid for a Phase of
+                                 EfiPciHostBridgeAllocateResources if
+                                 SubmitResources() has not been called for one
+                                 or more PCI root bridges before this call
+  @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
+                                 This error is valid for a Phase of
+                                 EfiPciHostBridgeSetResources.
+  @retval EFI_INVALID_PARAMETER  Invalid phase parameter
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources. This error is valid for a
+                                 Phase of EfiPciHostBridgeAllocateResources if
+                                 the previously submitted resource requests
+                                 cannot be fulfilled or were only partially
+                                 fulfilled.
+  @retval EFI_SUCCESS            The notification was accepted without any
+                                 errors.
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE     Phase
+  )
+{
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
+  PCI_RESOURCE_TYPE         Index;
+  LIST_ENTRY                *List;
+  EFI_PHYSICAL_ADDRESS      BaseAddress;
+  UINT64                    AddrLen;
+  UINTN                     BitsOfAlignment;
+  EFI_STATUS                Status;
+  EFI_STATUS                ReturnStatus;
+
+  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+  switch (Phase) {
+    case EfiPciHostBridgeBeginEnumeration:
+      if (HostBridgeInstance->CanRestarted) {
+        //
+        // Reset the Each Root Bridge
+        //
+        List = HostBridgeInstance->Head.ForwardLink;
+
+        while (List != &HostBridgeInstance->Head) {
+          RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+          for (Index = TypeIo; Index < TypeMax; Index++) {
+            RootBridgeInstance->ResAllocNode[Index].Type   = Index;
+            RootBridgeInstance->ResAllocNode[Index].Base   = 0;
+            RootBridgeInstance->ResAllocNode[Index].Length = 0;
+            RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+          }
+
+          List = List->ForwardLink;
+        }
+
+        HostBridgeInstance->ResourceSubmited = FALSE;
+        HostBridgeInstance->CanRestarted     = TRUE;
+      } else {
+        //
+        // Can not restart
+        //
+        return EFI_NOT_READY;
+      }
+
+      break;
+
+    case EfiPciHostBridgeEndEnumeration:
+      break;
+
+    case EfiPciHostBridgeBeginBusAllocation:
+      //
+      // No specific action is required here, can perform any chipset specific
+      // programing
+      //
+      HostBridgeInstance->CanRestarted = FALSE;
+      break;
+
+    case EfiPciHostBridgeEndBusAllocation:
+      //
+      // No specific action is required here, can perform any chipset specific
+      // programing
+      //
+      // HostBridgeInstance->CanRestarted = FALSE;
+      break;
+
+    case EfiPciHostBridgeBeginResourceAllocation:
+      //
+      // No specific action is required here, can perform any chipset specific
+      // programing
+      //
+      // HostBridgeInstance->CanRestarted = FALSE;
+      break;
+
+    case EfiPciHostBridgeAllocateResources:
+      ReturnStatus = EFI_SUCCESS;
+      if (HostBridgeInstance->ResourceSubmited) {
+        //
+        // Take care of the resource dependencies between the root bridges
+        //
+        List = HostBridgeInstance->Head.ForwardLink;
+
+        while (List != &HostBridgeInstance->Head) {
+          RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+          for (Index = TypeIo; Index < TypeBus; Index++) {
+            if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+              AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+
+              //
+              // Get the number of '1' in Alignment.
+              //
+              BitsOfAlignment =
+                (UINTN)(HighBitSet64 (
+                          RootBridgeInstance->ResAllocNode[Index].Alignment
+                          ) + 1);
+
+              switch (Index) {
+                case TypeIo:
+                  //
+                  // It is impossible for this chipset to align 0xFFFF for IO16
+                  // So clear it
+                  //
+                  if (BitsOfAlignment >= 16) {
+                    BitsOfAlignment = 0;
+                  }
+
+                  Status = gDS->AllocateIoSpace (
+                                  EfiGcdAllocateAnySearchBottomUp,
+                                  EfiGcdIoTypeIo,
+                                  BitsOfAlignment,
+                                  AddrLen,
+                                  &BaseAddress,
+                                  mDriverImageHandle,
+                                  NULL
+                                  );
+
+                  if (!EFI_ERROR (Status)) {
+                    RootBridgeInstance->ResAllocNode[Index].Base =
+                      (UINTN)BaseAddress;
+                    RootBridgeInstance->ResAllocNode[Index].Status =
+                      ResAllocated;
+                  } else {
+                    ReturnStatus = Status;
+                    if (Status != EFI_OUT_OF_RESOURCES) {
+                      RootBridgeInstance->ResAllocNode[Index].Length = 0;
+                    }
+                  }
+
+                  break;
+
+                case TypeMem32:
+                  //
+                  // It is impossible for this chipset to align 0xFFFFFFFF for
+                  // Mem32
+                  // So clear it
+                  //
+
+                  if (BitsOfAlignment >= 32) {
+                    BitsOfAlignment = 0;
+                  }
+
+                  Status = gDS->AllocateMemorySpace (
+                                  EfiGcdAllocateAnySearchBottomUp,
+                                  EfiGcdMemoryTypeMemoryMappedIo,
+                                  BitsOfAlignment,
+                                  AddrLen,
+                                  &BaseAddress,
+                                  mDriverImageHandle,
+                                  NULL
+                                  );
+
+                  if (!EFI_ERROR (Status)) {
+                    // We were able to allocate the PCI memory
+                    RootBridgeInstance->ResAllocNode[Index].Base =
+                      (UINTN)BaseAddress;
+                    RootBridgeInstance->ResAllocNode[Index].Status =
+                      ResAllocated;
+                  } else {
+                    // Not able to allocate enough PCI memory
+                    ReturnStatus = Status;
+
+                    if (Status != EFI_OUT_OF_RESOURCES) {
+                      RootBridgeInstance->ResAllocNode[Index].Length = 0;
+                    }
+
+                    ASSERT (FALSE);
+                  }
+
+                  break;
+
+                case TypePMem32:
+                case TypeMem64:
+                case TypePMem64:
+                  ReturnStatus = EFI_ABORTED;
+                  break;
+                default:
+                  ASSERT (FALSE);
+                  break;
+              }  // end switch
+            }
+          }
+
+          List = List->ForwardLink;
+        }
+
+        return ReturnStatus;
+      } else {
+        return EFI_NOT_READY;
+      }
+
+      break;
+
+    case EfiPciHostBridgeSetResources:
+      break;
+
+    case EfiPciHostBridgeFreeResources:
+      ReturnStatus = EFI_SUCCESS;
+      List         = HostBridgeInstance->Head.ForwardLink;
+      while (List != &HostBridgeInstance->Head) {
+        RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+        for (Index = TypeIo; Index < TypeBus; Index++) {
+          if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
+            AddrLen     = RootBridgeInstance->ResAllocNode[Index].Length;
+            BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
+            switch (Index) {
+              case TypeIo:
+                Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
+                if (EFI_ERROR (Status)) {
+                  ReturnStatus = Status;
+                }
+
+                break;
+
+              case TypeMem32:
+                Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
+                if (EFI_ERROR (Status)) {
+                  ReturnStatus = Status;
+                }
+
+                break;
+
+              case TypePMem32:
+                break;
+
+              case TypeMem64:
+                break;
+
+              case TypePMem64:
+                break;
+
+              default:
+                ASSERT (FALSE);
+                break;
+            } // end switch
+
+            RootBridgeInstance->ResAllocNode[Index].Type   = Index;
+            RootBridgeInstance->ResAllocNode[Index].Base   = 0;
+            RootBridgeInstance->ResAllocNode[Index].Length = 0;
+            RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
+          }
+        }
+
+        List = List->ForwardLink;
+      }
+
+      HostBridgeInstance->ResourceSubmited = FALSE;
+      HostBridgeInstance->CanRestarted     = TRUE;
+      return ReturnStatus;
+
+    case EfiPciHostBridgeEndResourceAllocation:
+      HostBridgeInstance->CanRestarted = FALSE;
+      break;
+
+    default:
+      return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return the device handle of the next PCI root bridge that is associated with
+  this Host Bridge.
+
+  This function is called multiple times to retrieve the device handles of all
+  the PCI root bridges that are associated with this PCI host bridge. Each PCI
+  host bridge is associated with one or more PCI root bridges. On each call,
+  the handle that was returned by the previous call is passed into the
+  interface, and on output the interface returns the device handle of the next
+  PCI root bridge. The caller can use the handle to obtain the instance of the
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
+  PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
+  enumerator must enumerate the PCI root bridges in the order that they are
+  returned by this function.
+
+  For D945 implementation, there is only one root bridge in PCI host bridge.
+
+  @param[in]       This              The instance pointer of
+                                     EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+  @param[in, out]  RootBridgeHandle  Returns the device handle of the next PCI
+                                     root bridge.
+
+  @retval EFI_SUCCESS            If parameter RootBridgeHandle = NULL, then
+                                 return the first Rootbridge handle of the
+                                 specific Host bridge and return EFI_SUCCESS.
+  @retval EFI_NOT_FOUND          Can not find the any more root bridge in
+                                 specific host bridge.
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not an EFI_HANDLE that was
+                                 returned on a previous call to
+                                 GetNextRootBridge().
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge (
+  IN       EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN OUT   EFI_HANDLE                                        *RootBridgeHandle
+  )
+{
+  BOOLEAN                   NoRootBridge;
+  LIST_ENTRY                *List;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
+
+  NoRootBridge       = TRUE;
+  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+  List               = HostBridgeInstance->Head.ForwardLink;
+
+  while (List != &HostBridgeInstance->Head) {
+    NoRootBridge       = FALSE;
+    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+    if (*RootBridgeHandle == NULL) {
+      //
+      // Return the first Root Bridge Handle of the Host Bridge
+      //
+      *RootBridgeHandle = RootBridgeInstance->Handle;
+      return EFI_SUCCESS;
+    } else {
+      if (*RootBridgeHandle == RootBridgeInstance->Handle) {
+        //
+        // Get next if have
+        //
+        List = List->ForwardLink;
+        if (List != &HostBridgeInstance->Head) {
+          RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+          *RootBridgeHandle  = RootBridgeInstance->Handle;
+          return EFI_SUCCESS;
+        } else {
+          return EFI_NOT_FOUND;
+        }
+      }
+    }
+
+    List = List->ForwardLink;
+  } // end while
+
+  if (NoRootBridge) {
+    return EFI_NOT_FOUND;
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+}
+
+/**
+  Returns the allocation attributes of a PCI root bridge.
+
+  The function returns the allocation attributes of a specific PCI root bridge.
+  The attributes can vary from one PCI root bridge to another. These attributes
+  are different from the decode-related attributes that are returned by the
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
+  RootBridgeHandle parameter is used to specify the instance of the PCI root
+  bridge. The device handles of all the root bridges that are associated with
+  this host bridge must be obtained by calling GetNextRootBridge(). The
+  attributes are static in the sense that they do not change during or after
+  the enumeration process. The hardware may provide mechanisms to change the
+  attributes on the fly, but such changes must be completed before
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
+  values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
+  "Related Definitions" below. The caller uses these attributes to combine
+  multiple resource requests.
+
+  For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
+  bus enumerator needs to include requests for the prefetchable memory in the
+  nonprefetchable memory pool and not request any prefetchable memory.
+
+  Attribute                             Description
+  ------------------------------------  ---------------------------------------
+  EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM  If this bit is set, then the PCI root
+                                        bridge does not support separate
+                                        windows for nonprefetchable and
+                                        prefetchable memory. A PCI bus driver
+                                        needs to include requests for
+                                        prefetchable memory in the
+                                        nonprefetchable memory pool.
+
+  EFI_PCI_HOST_BRIDGE_MEM64_DECODE      If this bit is set, then the PCI root
+                                        bridge supports 64-bit memory windows.
+                                        If this bit is not set, the PCI bus
+                                        driver needs to include requests for a
+                                        64-bit memory address in the
+                                        corresponding 32-bit memory pool.
+
+  @param[in]   This               The instance pointer of
+                                  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+  @param[in]   RootBridgeHandle   The device handle of the PCI root bridge in
+                                  which the caller is interested. Type
+                                  EFI_HANDLE is defined in
+                                  InstallProtocolInterface() in the UEFI 2.0
+                                  Specification.
+  @param[out]  Attributes         The pointer to attribte of root bridge, it is
+                                  output parameter
+
+  @retval EFI_INVALID_PARAMETER   Attribute pointer is NULL
+  @retval EFI_INVALID_PARAMETER   RootBridgehandle is invalid.
+  @retval EFI_SUCCESS             Success to get attribute of interested root
+                                  bridge.
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN  EFI_HANDLE                                        RootBridgeHandle,
+  OUT UINT64                                            *Attributes
+  )
+{
+  LIST_ENTRY                *List;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
+
+  if (Attributes == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+  List               = HostBridgeInstance->Head.ForwardLink;
+
+  while (List != &HostBridgeInstance->Head) {
+    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+    if (RootBridgeHandle == RootBridgeInstance->Handle) {
+      *Attributes = RootBridgeInstance->RootBridgeAttrib;
+      return EFI_SUCCESS;
+    }
+
+    List = List->ForwardLink;
+  }
+
+  //
+  // RootBridgeHandle is not an EFI_HANDLE
+  // that was returned on a previous call to GetNextRootBridge()
+  //
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+  Sets up the specified PCI root bridge for the bus enumeration process.
+
+  This member function sets up the root bridge for bus enumeration and returns
+  the PCI bus range over which the search should be performed in ACPI 2.0
+  resource descriptor format.
+
+  @param[in]   This              The
+                                 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                                 instance.
+  @param[in]   RootBridgeHandle  The PCI Root Bridge to be set up.
+  @param[out]  Configuration     Pointer to the pointer to the PCI bus resource
+                                 descriptor.
+
+  @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
+  @retval EFI_OUT_OF_RESOURCES  Fail to allocate ACPI resource descriptor tag.
+  @retval EFI_SUCCESS           Sucess to allocate ACPI resource descriptor.
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN  EFI_HANDLE                                        RootBridgeHandle,
+  OUT VOID                                              **Configuration
+  )
+{
+  LIST_ENTRY                *List;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
+  VOID                      *Buffer;
+  UINT8                     *Temp;
+  UINT64                    BusStart;
+  UINT64                    BusEnd;
+
+  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+  List               = HostBridgeInstance->Head.ForwardLink;
+
+  while (List != &HostBridgeInstance->Head) {
+    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+    if (RootBridgeHandle == RootBridgeInstance->Handle) {
+      //
+      // Set up the Root Bridge for Bus Enumeration
+      //
+      BusStart = RootBridgeInstance->BusBase;
+      BusEnd   = RootBridgeInstance->BusLimit;
+      //
+      // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
+      //
+
+      Buffer = AllocatePool (
+                 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
+                 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+                 );
+      if (Buffer == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      Temp = (UINT8 *)Buffer;
+
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc                  = 0x8A;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len                   = 0x2B;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType               = 2;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag               = 0;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag          = 0;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity  = 0;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin          = BusStart;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax          = 0;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
+      ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen               =
+        BusEnd - BusStart + 1;
+
+      Temp                                            = Temp + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+      ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc     = 0x79;
+      ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
+
+      *Configuration = Buffer;
+      return EFI_SUCCESS;
+    }
+
+    List = List->ForwardLink;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+  Programs the PCI root bridge hardware so that it decodes the specified PCI
+  bus range.
+
+  This member function programs the specified PCI root bridge to decode the bus
+  range that is specified by the input parameter Configuration.
+  The bus range information is specified in terms of the ACPI 2.0 resource
+  descriptor format.
+
+  @param[in] This              The
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                               instance
+  @param[in] RootBridgeHandle  The PCI Root Bridge whose bus range is to be
+                               programmed
+  @param[in] Configuration     The pointer to the PCI bus resource descriptor
+
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
+                                 handle.
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
+  @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI
+                                 2.0 resource descriptor.
+  @retval EFI_INVALID_PARAMETER  Configuration does not include a valid ACPI
+                                 2.0 bus resource descriptor.
+  @retval EFI_INVALID_PARAMETER  Configuration includes valid ACPI 2.0 resource
+                                 descriptors other than bus descriptors.
+  @retval EFI_INVALID_PARAMETER  Configuration contains one or more invalid
+                                 ACPI resource descriptors.
+  @retval EFI_INVALID_PARAMETER  "Address Range Minimum" is invalid for this
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this
+                                 root bridge.
+  @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
+  @retval EFI_SUCCESS            The bus range for the PCI root bridge was
+                                 programmed.
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN EFI_HANDLE                                        RootBridgeHandle,
+  IN VOID                                              *Configuration
+  )
+{
+  LIST_ENTRY                *List;
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
+  UINT8                     *Ptr;
+  UINTN                     BusStart;
+  UINTN                     BusEnd;
+  UINTN                     BusLen;
+
+  if (Configuration == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Ptr = Configuration;
+
+  //
+  // Check the Configuration is valid
+  //
+  if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+  if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+  List               = HostBridgeInstance->Head.ForwardLink;
+
+  Ptr = Configuration;
+
+  while (List != &HostBridgeInstance->Head) {
+    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+    if (RootBridgeHandle == RootBridgeInstance->Handle) {
+      EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Desc;
+
+      Desc     = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
+      BusStart = (UINTN)Desc->AddrRangeMin;
+      BusLen   = (UINTN)Desc->AddrLen;
+      BusEnd   = BusStart + BusLen - 1;
+
+      if (BusStart > BusEnd) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      if ((BusStart < RootBridgeInstance->BusBase) ||
+          (BusEnd > RootBridgeInstance->BusLimit))
+      {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      //
+      // Update the Bus Range
+      //
+      RootBridgeInstance->ResAllocNode[TypeBus].Base   = BusStart;
+      RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
+      RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
+
+      //
+      // Program the Root Bridge Hardware
+      //
+
+      return EFI_SUCCESS;
+    }
+
+    List = List->ForwardLink;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+  Submits the I/O and memory resource requirements for the specified PCI root
+  bridge.
+
+  This function is used to submit all the I/O and memory resources that are
+  required by the specified PCI root bridge. The input parameter Configuration
+  is used to specify the following:
+  - The various types of resources that are required
+  - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+  @param[in] This              Pointer to the
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                               instance.
+  @param[in] RootBridgeHandle  The PCI root bridge whose I/O and memory
+                               resource requirements are being submitted.
+  @param[in] Configuration     The pointer to the PCI I/O and PCI memory
+                               resource descriptor.
+
+  @retval EFI_SUCCESS            The I/O and memory resource requests for a PCI
+                                 root bridge were accepted.
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
+                                 handle.
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
+  @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI
+                                 2.0 resource descriptor.
+  @retval EFI_INVALID_PARAMETER  Configuration includes requests for one or
+                                 more resource types that are not supported by
+                                 this PCI root bridge. This error will happen
+                                 if the caller did not combine resources
+                                 according to Attributes that were returned by
+                                 GetAllocAttributes().
+  @retval EFI_INVALID_PARAMETER  Address Range Maximum" is invalid.
+  @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  "Address Space Granularity" is invalid for
+                                 this PCI root bridge.
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN EFI_HANDLE                                        RootBridgeHandle,
+  IN VOID                                              *Configuration
+  )
+{
+  LIST_ENTRY                         *List;
+  PCI_HOST_BRIDGE_INSTANCE           *HostBridgeInstance;
+  PCI_ROOT_BRIDGE_INSTANCE           *RootBridgeInstance;
+  UINT8                              *Temp;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Ptr;
+  UINT64                             AddrLen;
+  UINT64                             Alignment;
+
+  //
+  // Check the input parameter: Configuration
+  //
+  if (Configuration == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+  List               = HostBridgeInstance->Head.ForwardLink;
+
+  Temp = (UINT8 *)Configuration;
+  while ( *Temp == 0x8A) {
+    Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+  }
+
+  if (*Temp != 0x79) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Temp = (UINT8 *)Configuration;
+  while (List != &HostBridgeInstance->Head) {
+    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+    if (RootBridgeHandle == RootBridgeInstance->Handle) {
+      while ( *Temp == 0x8A) {
+        Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp;
+
+        //
+        // Check Address Length
+        //
+        if (Ptr->AddrLen > 0xffffffff) {
+          return EFI_INVALID_PARAMETER;
+        }
+
+        //
+        // Check address range alignment
+        //
+        if ((Ptr->AddrRangeMax >= 0xffffffff) ||
+            (Ptr->AddrRangeMax != (GetPowerOfTwo64 (
+                                     Ptr->AddrRangeMax + 1
+                                     ) - 1)))
+        {
+          return EFI_INVALID_PARAMETER;
+        }
+
+        switch (Ptr->ResType) {
+          case 0:
+
+            //
+            // Check invalid Address Sapce Granularity
+            //
+            if (Ptr->AddrSpaceGranularity != 32) {
+              return EFI_INVALID_PARAMETER;
+            }
+
+            //
+            // check the memory resource request is supported by PCI root bridge
+            //
+            if ((RootBridgeInstance->RootBridgeAttrib ==
+                 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) &&
+                (Ptr->SpecificFlag == 0x06))
+            {
+              return EFI_INVALID_PARAMETER;
+            }
+
+            AddrLen   = Ptr->AddrLen;
+            Alignment = Ptr->AddrRangeMax;
+            if (Ptr->AddrSpaceGranularity == 32) {
+              if (Ptr->SpecificFlag == 0x06) {
+                //
+                // Apply from GCD
+                //
+                RootBridgeInstance->ResAllocNode[TypePMem32].Status =
+                  ResSubmitted;
+              } else {
+                RootBridgeInstance->ResAllocNode[TypeMem32].Length    = AddrLen;
+                RootBridgeInstance->ResAllocNode[TypeMem32].Alignment =
+                  Alignment;
+                RootBridgeInstance->ResAllocNode[TypeMem32].Status =
+                  ResRequested;
+                HostBridgeInstance->ResourceSubmited = TRUE;
+              }
+            }
+
+            if (Ptr->AddrSpaceGranularity == 64) {
+              if (Ptr->SpecificFlag == 0x06) {
+                RootBridgeInstance->ResAllocNode[TypePMem64].Status =
+                  ResSubmitted;
+              } else {
+                RootBridgeInstance->ResAllocNode[TypeMem64].Status =
+                  ResSubmitted;
+              }
+            }
+
+            break;
+
+          case 1:
+            AddrLen                                            = (UINTN)Ptr->AddrLen;
+            Alignment                                          = (UINTN)Ptr->AddrRangeMax;
+            RootBridgeInstance->ResAllocNode[TypeIo].Length    = AddrLen;
+            RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
+            RootBridgeInstance->ResAllocNode[TypeIo].Status    = ResRequested;
+            HostBridgeInstance->ResourceSubmited               = TRUE;
+            break;
+
+          default:
+            break;
+        }
+
+        Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+      }
+
+      return EFI_SUCCESS;
+    }
+
+    List = List->ForwardLink;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+   Returns the proposed resource settings for the specified PCI root bridge.
+
+   This member function returns the proposed resource settings for the
+   specified PCI root bridge. The proposed resource settings are prepared when
+   NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
+   The output parameter Configuration specifies the following:
+   - The various types of resources, excluding bus resources, that are
+     allocated
+   - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+   @param[in]  This              Pointer to the
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                                 instance.
+   @param[in]  RootBridgeHandle  The PCI root bridge handle. Type EFI_HANDLE is
+                                 defined in InstallProtocolInterface() in the
+                                 UEFI 2.0 Specification.
+   @param[out] Configuration     The pointer to the pointer to the PCI I/O and
+                                 memory resource descriptor.
+
+   @retval EFI_SUCCESS            The requested parameters were returned.
+   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
+                                  handle.
+   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
+   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                  lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN  EFI_HANDLE                                        RootBridgeHandle,
+  OUT VOID                                              **Configuration
+  )
+{
+  LIST_ENTRY                         *List;
+  PCI_HOST_BRIDGE_INSTANCE           *HostBridgeInstance;
+  PCI_ROOT_BRIDGE_INSTANCE           *RootBridgeInstance;
+  UINTN                              Index;
+  UINTN                              Number;
+  VOID                               *Buffer;
+  UINT8                              *Temp;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Ptr;
+  UINT64                             ResStatus;
+
+  Buffer = NULL;
+  Number = 0;
+  //
+  // Get the Host Bridge Instance from the resource allocation protocol
+  //
+  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+  List               = HostBridgeInstance->Head.ForwardLink;
+
+  //
+  // Enumerate the root bridges in this host bridge
+  //
+  while (List != &HostBridgeInstance->Head) {
+    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+    if (RootBridgeHandle == RootBridgeInstance->Handle) {
+      for (Index = 0; Index < TypeBus; Index++) {
+        if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+          Number++;
+        }
+      }
+
+      if (Number ==  0) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      Buffer = AllocateZeroPool (
+                 Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
+                 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+                 );
+      if (Buffer == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      Temp = Buffer;
+      for (Index = 0; Index < TypeBus; Index++) {
+        if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
+          Ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp;
+          ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
+
+          switch (Index) {
+            case TypeIo:
+              //
+              // Io
+              //
+              Ptr->Desc                  = 0x8A;
+              Ptr->Len                   = 0x2B;
+              Ptr->ResType               = 1;
+              Ptr->GenFlag               = 0;
+              Ptr->SpecificFlag          = 0;
+              Ptr->AddrRangeMin          = RootBridgeInstance->ResAllocNode[Index].Base;
+              Ptr->AddrRangeMax          = 0;
+              Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
+                                           EFI_RESOURCE_SATISFIED :
+                                           EFI_RESOURCE_LESS;
+              Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+              break;
+
+            case TypeMem32:
+              //
+              // Memory 32
+              //
+              Ptr->Desc                  = 0x8A;
+              Ptr->Len                   = 0x2B;
+              Ptr->ResType               = 0;
+              Ptr->GenFlag               = 0;
+              Ptr->SpecificFlag          = 0;
+              Ptr->AddrSpaceGranularity  = 32;
+              Ptr->AddrRangeMin          = RootBridgeInstance->ResAllocNode[Index].Base;
+              Ptr->AddrRangeMax          = 0;
+              Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
+                                           EFI_RESOURCE_SATISFIED :
+                                           EFI_RESOURCE_LESS;
+              Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
+              break;
+
+            case TypePMem32:
+              //
+              // Prefetch memory 32
+              //
+              Ptr->Desc                  = 0x8A;
+              Ptr->Len                   = 0x2B;
+              Ptr->ResType               = 0;
+              Ptr->GenFlag               = 0;
+              Ptr->SpecificFlag          = 6;
+              Ptr->AddrSpaceGranularity  = 32;
+              Ptr->AddrRangeMin          = 0;
+              Ptr->AddrRangeMax          = 0;
+              Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+              Ptr->AddrLen               = 0;
+              break;
+
+            case TypeMem64:
+              //
+              // Memory 64
+              //
+              Ptr->Desc                  = 0x8A;
+              Ptr->Len                   = 0x2B;
+              Ptr->ResType               = 0;
+              Ptr->GenFlag               = 0;
+              Ptr->SpecificFlag          = 0;
+              Ptr->AddrSpaceGranularity  = 64;
+              Ptr->AddrRangeMin          = 0;
+              Ptr->AddrRangeMax          = 0;
+              Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+              Ptr->AddrLen               = 0;
+              break;
+
+            case TypePMem64:
+              //
+              // Prefetch memory 64
+              //
+              Ptr->Desc                  = 0x8A;
+              Ptr->Len                   = 0x2B;
+              Ptr->ResType               = 0;
+              Ptr->GenFlag               = 0;
+              Ptr->SpecificFlag          = 6;
+              Ptr->AddrSpaceGranularity  = 64;
+              Ptr->AddrRangeMin          = 0;
+              Ptr->AddrRangeMax          = 0;
+              Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+              Ptr->AddrLen               = 0;
+              break;
+          }
+
+          Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+        }
+      }
+
+      ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc     = 0x79;
+      ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
+
+      *Configuration = Buffer;
+
+      return EFI_SUCCESS;
+    }
+
+    List = List->ForwardLink;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+  Provides the hooks from the PCI bus driver to every PCI controller
+  (device/function) at various stages of the PCI enumeration process that allow
+  the host bridge driver to preinitialize individual PCI controllers before
+  enumeration.
+
+  This function is called during the PCI enumeration process. No specific
+  action is expected from this member function. It allows the host bridge
+  driver to preinitialize individual PCI controllers before enumeration.
+
+  @param This              Pointer to the
+                           EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                           instance.
+  @param RootBridgeHandle  The associated PCI root bridge handle. Type
+                           EFI_HANDLE is defined in InstallProtocolInterface()
+                           in the UEFI 2.0 Specification.
+  @param PciAddress        The address of the PCI device on the PCI bus. This
+                           address can be passed to the
+                           EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
+                           access the PCI configuration space of the device.
+                           See Table 12-1 in the UEFI 2.0 Specification for the
+                           definition of
+                           EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
+  @param Phase             The phase of the PCI device enumeration.
+
+  @retval EFI_SUCCESS              The requested parameters were returned.
+  @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge
+                                   handle.
+  @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined
+                                   in
+                                  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
+  @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error.
+                                   The PCI enumerator should not enumerate this
+                                   device, including its child devices if it is
+                                   a PCI-to-PCI bridge.
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN  EFI_HANDLE                                        RootBridgeHandle,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       PciAddress,
+  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE      Phase
+  )
+{
+  PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
+  PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
+  LIST_ENTRY                *List;
+
+  HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+  List               = HostBridgeInstance->Head.ForwardLink;
+
+  //
+  // Enumerate the root bridges in this host bridge
+  //
+  while (List != &HostBridgeInstance->Head) {
+    RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
+    if (RootBridgeHandle == RootBridgeInstance->Handle) {
+      break;
+    }
+
+    List = List->ForwardLink;
+  }
+
+  if (List == &HostBridgeInstance->Head) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
new file mode 100644
index 0000000000..8182697994
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.h
@@ -0,0 +1,624 @@
+/** @file
+  Implementation of PciHostBridge.h
+  The Header file of the Pci Host Bridge Driver
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PCI_HOST_BRIDGE_H_
+#define PCI_HOST_BRIDGE_H_
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/Metronome.h>
+#include <Protocol/DevicePath.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+
+//
+// Hard code the host bridge number in the platform.
+// In this chipset, there is only one host bridge.
+//
+#define HOST_BRIDGE_NUMBER  1
+
+#define MAX_PCI_DEVICE_NUMBER    31
+#define MAX_PCI_FUNCTION_NUMBER  7
+#define MAX_PCI_REG_ADDRESS      0xFF
+
+typedef enum {
+  IoOperation,
+  MemOperation,
+  PciOperation
+} OPERATION_TYPE;
+
+#define PCI_HOST_BRIDGE_SIGNATURE  SIGNATURE_32('e', 'h', 's', 't')
+typedef struct {
+  UINTN                                               Signature;
+  EFI_HANDLE                                          HostBridgeHandle;
+  UINTN                                               RootBridgeNumber;
+  LIST_ENTRY                                          Head;
+  BOOLEAN                                             ResourceSubmited;
+  BOOLEAN                                             CanRestarted;
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL    ResAlloc;
+} PCI_HOST_BRIDGE_INSTANCE;
+
+#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) \
+  CR(a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
+
+//
+//  HostBridge Resource Allocation interface
+//
+
+/**
+  These are the notifications from the PCI bus driver that it is about to enter
+  a certain phase of the PCI enumeration process.
+
+  This member function can be used to notify the host bridge driver to perform
+  specific actions, including any chipset-specific initialization, so that the
+  chipset is ready to enter the next phase. Eight notification points are
+  defined at this time. See belows:
+
+  EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures
+                                         and internal data structures. The PCI
+                                         enumerator should issue this
+                                         notification before starting a fresh
+                                         enumeration process. Enumeration
+                                         cannot be restarted after sending any
+                                         other notification such as
+                                         EfiPciHostBridgeBeginBusAllocation.
+
+  EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to
+                                         begin. No specific action is required
+                                         here. This notification can be used to
+                                         perform any chipset-specific
+                                         programming.
+
+  EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming
+                                         phase is complete. No specific action
+                                         is required here. This notification
+                                         can be used to perform any
+                                         chipset-specific programming.
+
+  EfiPciHostBridgeBeginResourceAllocation
+                                         The resource allocation phase is about
+                                         to begin. No specific action is
+                                         required here. This notification can
+                                         be used to perform any
+                                         chipset-specific programming.
+
+  EfiPciHostBridgeAllocateResources      Allocates resources per previously
+                                         submitted requests for all the PCI
+                                         root bridges. These resource settings
+                                         are returned on the next call to
+                                         GetProposedResources(). Before calling
+                                         NotifyPhase() with a Phase of
+                                         EfiPciHostBridgeAllocateResource, the
+                                         PCI bus enumerator is responsible for
+                                         gathering I/O and memory requests for
+                                         all the PCI root bridges and
+                                         submitting these requests using
+                                         SubmitResources(). This function pads
+                                         the resource amount to suit the root
+                                         bridge hardware, takes care of
+                                         dependencies between the PCI root
+                                         bridges, and calls the Global
+                                         Coherency Domain (GCD) with the
+                                         allocation request. In the case of
+                                         padding, the allocated range could be
+                                         bigger than what was requested.
+
+  EfiPciHostBridgeSetResources           Programs the host bridge hardware to
+                                         decode previously allocated resources
+                                         (proposed resources) for all the PCI
+                                         root bridges. After the hardware is
+                                         programmed, reassigning resources will
+                                         not be supported. The bus settings are
+                                         not affected.
+
+  EfiPciHostBridgeFreeResources          Deallocates resources that were
+                                         previously allocated for all the PCI
+                                         root bridges and resets the I/O and
+                                         memory apertures to their initial
+                                         state. The bus settings are not
+                                         affected. If the request to allocate
+                                         resources fails, the PCI enumerator
+                                         can use this notification to
+                                         deallocate previous resources, adjust
+                                         the requests, and retry allocation.
+
+  EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is
+                                         completed. No specific action is
+                                         required here. This notification can
+                                         be used to perform any chipsetspecific
+                                         programming.
+
+  @param[in] This                The instance pointer of
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+  @param[in] Phase               The phase during enumeration
+
+  @retval EFI_NOT_READY          This phase cannot be entered at this time. For
+                                 example, this error is valid for a Phase of
+                                 EfiPciHostBridgeAllocateResources if
+                                 SubmitResources() has not been called for one
+                                 or more PCI root bridges before this call
+
+  @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
+                                 This error is valid for a Phase of
+                                 EfiPciHostBridgeSetResources.
+
+  @retval EFI_INVALID_PARAMETER  Invalid phase parameter
+
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources. This error is valid for a
+                                 Phase of EfiPciHostBridgeAllocateResources if
+                                 the previously submitted resource requests
+                                 cannot be fulfilled or were only partially
+                                 fulfilled.
+
+  @retval EFI_SUCCESS            The notification was accepted without any
+                                 errors.
+**/
+EFI_STATUS
+EFIAPI
+NotifyPhase (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE     Phase
+  );
+
+/**
+  Return the device handle of the next PCI root bridge that is associated with
+  this Host Bridge.
+
+  This function is called multiple times to retrieve the device handles of all
+  the PCI root bridges that are associated with this PCI host bridge. Each PCI
+  host bridge is associated with one or more PCI root bridges. On each call,
+  the handle that was returned by the previous call is passed into the
+  interface, and on output the interface returns the device handle of the next
+  PCI root bridge. The caller can use the handle to obtain the instance of the
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
+  PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
+  enumerator must enumerate the PCI root bridges in the order that they are
+  returned by this function.
+
+  For D945 implementation, there is only one root bridge in PCI host bridge.
+
+  @param[in]       This              The instance pointer of
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+  @param[in, out]  RootBridgeHandle  Returns the device handle of the next PCI
+                                     root bridge.
+
+  @retval EFI_SUCCESS            If parameter RootBridgeHandle = NULL, then
+                                 return the first Rootbridge handle of the
+                                 specific Host bridge and return EFI_SUCCESS.
+
+  @retval EFI_NOT_FOUND          Can not find the any more root bridge in
+                                 specific host bridge.
+
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not an EFI_HANDLE that was
+                                 returned on a previous call to
+                                 GetNextRootBridge().
+**/
+EFI_STATUS
+EFIAPI
+GetNextRootBridge (
+  IN       EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN OUT   EFI_HANDLE                                        *RootBridgeHandle
+  );
+
+/**
+  Returns the allocation attributes of a PCI root bridge.
+
+  The function returns the allocation attributes of a specific PCI root bridge.
+  The attributes can vary from one PCI root bridge to another. These attributes
+  are different from the decode-related attributes that are returned by the
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
+  RootBridgeHandle parameter is used to specify the instance of the PCI root
+  bridge. The device handles of all the root bridges that are associated with
+  this host bridge must be obtained by calling GetNextRootBridge(). The
+  attributes are static in the sense that they do not change during or after
+  the enumeration process. The hardware may provide mechanisms to change the
+  attributes on the fly, but such changes must be completed before
+  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
+  values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
+  "Related Definitions" below. The caller uses these attributes to combine
+  multiple resource requests.
+
+  For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
+  bus enumerator needs to include requests for the prefetchable memory in the
+  nonprefetchable memory pool and not request any prefetchable memory.
+
+  Attribute                             Description
+  ------------------------------------  ---------------------------------------
+  EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM  If this bit is set, then the PCI root
+                                        bridge does not support separate
+                                        windows for nonprefetchable and
+                                        prefetchable memory. A PCI bus driver
+                                        needs to include requests for
+                                        prefetchable memory in the
+                                        nonprefetchable memory pool.
+
+  EFI_PCI_HOST_BRIDGE_MEM64_DECODE      If this bit is set, then the PCI root
+                                        bridge supports 64-bit memory windows.
+                                        If this bit is not set, the PCI bus
+                                        driver needs to include requests for a
+                                        64-bit memory address in the
+                                        corresponding 32-bit memory pool.
+
+  @param[in]   This               The instance pointer of
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+  @param[in]   RootBridgeHandle   The device handle of the PCI root bridge in
+                                  which the caller is interested. Type
+                                  EFI_HANDLE is defined in
+                                  InstallProtocolInterface() in the UEFI 2.0
+                                  Specification.
+  @param[out]  Attributes         The pointer to attribte of root bridge, it is
+                                  output parameter
+
+  @retval EFI_INVALID_PARAMETER   Attribute pointer is NULL
+
+  @retval EFI_INVALID_PARAMETER   RootBridgehandle is invalid.
+
+  @retval EFI_SUCCESS             Success to get attribute of interested root
+                                  bridge.
+**/
+EFI_STATUS
+EFIAPI
+GetAttributes (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN  EFI_HANDLE                                        RootBridgeHandle,
+  OUT UINT64                                            *Attributes
+  );
+
+/**
+  Sets up the specified PCI root bridge for the bus enumeration process.
+
+  This member function sets up the root bridge for bus enumeration and returns
+  the PCI bus range over which the search should be performed in ACPI 2.0
+  resource descriptor format.
+
+  @param[in]   This              The
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                                 instance.
+  @param[in]   RootBridgeHandle  The PCI Root Bridge to be set up.
+  @param[out]  Configuration     Pointer to the pointer to the PCI bus resource
+                                 descriptor.
+
+  @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
+
+  @retval EFI_OUT_OF_RESOURCES  Fail to allocate ACPI resource descriptor tag.
+
+  @retval EFI_SUCCESS           Sucess to allocate ACPI resource descriptor.
+**/
+EFI_STATUS
+EFIAPI
+StartBusEnumeration (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN  EFI_HANDLE                                        RootBridgeHandle,
+  OUT VOID                                              **Configuration
+  );
+
+/**
+  Programs the PCI root bridge hardware so that it decodes the specified PCI
+  bus range.
+
+  This member function programs the specified PCI root bridge to decode the bus
+  range that is specified by the input parameter Configuration.
+  The bus range information is specified in terms of the ACPI 2.0 resource
+  descriptor format.
+
+  @param[in] This              The
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                               instance
+  @param[in] RootBridgeHandle  The PCI Root Bridge whose bus range is to be
+                               programmed
+  @param[in] Configuration     The pointer to the PCI bus resource descriptor
+
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
+                                 handle.
+
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
+
+  @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI
+                                 2.0 resource descriptor.
+
+  @retval EFI_INVALID_PARAMETER  Configuration does not include a valid ACPI
+                                 2.0 bus resource descriptor.
+
+  @retval EFI_INVALID_PARAMETER  Configuration includes valid ACPI 2.0 resource
+                                 descriptors other than bus descriptors.
+
+  @retval EFI_INVALID_PARAMETER  Configuration contains one or more invalid
+                                 ACPI resource descriptors.
+
+  @retval EFI_INVALID_PARAMETER  "Address Range Minimum" is invalid for this
+                                 root bridge.
+
+  @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this
+                                 root bridge.
+
+  @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
+
+  @retval EFI_SUCCESS            The bus range for the PCI root bridge was
+                                 programmed.
+**/
+EFI_STATUS
+EFIAPI
+SetBusNumbers (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN EFI_HANDLE                                        RootBridgeHandle,
+  IN VOID                                              *Configuration
+  );
+
+/**
+  Submits the I/O and memory resource requirements for the specified PCI root
+  bridge.
+
+  This function is used to submit all the I/O and memory resources that are
+  required by the specified PCI root bridge. The input parameter Configuration
+  is used to specify the following:
+  - The various types of resources that are required
+  - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+  @param[in] This              Pointer to the
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                               instance.
+  @param[in] RootBridgeHandle  The PCI root bridge whose I/O and memory
+                               resource requirements are being submitted.
+  @param[in] Configuration     The pointer to the PCI I/O and PCI memory
+                               resource descriptor.
+
+  @retval EFI_SUCCESS            The I/O and memory resource requests for a PCI
+                                 root bridge were accepted.
+
+  @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
+                                 handle.
+
+  @retval EFI_INVALID_PARAMETER  Configuration is NULL.
+
+  @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI
+                                 2.0 resource descriptor.
+
+  @retval EFI_INVALID_PARAMETER  Configuration includes requests for one or
+                                 more resource types that are not supported by
+                                 this PCI root bridge. This error will happen
+                                 if the caller did not combine resources
+                                 according to Attributes that were returned by
+                                 GetAllocAttributes().
+
+  @retval EFI_INVALID_PARAMETER  Address Range Maximum" is invalid.
+
+  @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this PCI
+                                 root bridge.
+
+  @retval EFI_INVALID_PARAMETER  "Address Space Granularity" is invalid for
+                                 this PCI root bridge.
+**/
+EFI_STATUS
+EFIAPI
+SubmitResources (
+  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN EFI_HANDLE                                        RootBridgeHandle,
+  IN VOID                                              *Configuration
+  );
+
+/**
+   Returns the proposed resource settings for the specified PCI root bridge.
+
+   This member function returns the proposed resource settings for the
+   specified PCI root bridge. The proposed resource settings are prepared when
+   NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
+   The output parameter Configuration specifies the following:
+   - The various types of resources, excluding bus resources, that are
+     allocated
+   - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+   @param[in]  This              Pointer to the
+                               EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                                 instance.
+   @param[in]  RootBridgeHandle  The PCI root bridge handle. Type EFI_HANDLE is
+                                 defined in InstallProtocolInterface() in the
+                                 UEFI 2.0 Specification.
+   @param[out] Configuration     The pointer to the pointer to the PCI I/O and
+                                 memory resource descriptor.
+
+   @retval EFI_SUCCESS            The requested parameters were returned.
+
+   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
+                                  handle.
+
+   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
+
+   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                  lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+GetProposedResources (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN  EFI_HANDLE                                        RootBridgeHandle,
+  OUT VOID                                              **Configuration
+  );
+
+/**
+  Provides the hooks from the PCI bus driver to every PCI controller
+  (device/function) at various stages of the PCI enumeration process that allow
+  the host bridge driver to preinitialize individual PCI controllers before
+  enumeration.
+
+  This function is called during the PCI enumeration process. No specific
+  action is expected from this member function. It allows the host bridge
+  driver to preinitialize individual PCI controllers before enumeration.
+
+  @param This              Pointer to the
+                           EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+                           instance.
+  @param RootBridgeHandle  The associated PCI root bridge handle. Type
+                           EFI_HANDLE is defined in InstallProtocolInterface()
+                           in the UEFI 2.0 Specification.
+  @param PciAddress        The address of the PCI device on the PCI bus. This
+                           address can be passed to the
+                           EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
+                           access the PCI configuration space of the device.
+                           See Table 12-1 in the UEFI 2.0 Specification for the
+                           definition of
+                           EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
+  @param Phase             The phase of the PCI device enumeration.
+
+  @retval EFI_SUCCESS              The requested parameters were returned.
+
+  @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge
+                                   handle.
+
+  @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined
+                                   in
+                                  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
+
+  @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error.
+                                   The PCI enumerator should not enumerate this
+                                   device, including its child devices if it is
+                                   a PCI-to-PCI bridge.
+**/
+EFI_STATUS
+EFIAPI
+PreprocessController (
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
+  IN  EFI_HANDLE                                        RootBridgeHandle,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       PciAddress,
+  IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE      Phase
+  );
+
+//
+// Define resource status constant
+//
+#define EFI_RESOURCE_NONEXISTENT  0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS         0xFFFFFFFFFFFFFFFEULL
+
+//
+// Driver Instance Data Prototypes
+//
+
+typedef struct {
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION    Operation;
+  UINTN                                        NumberOfBytes;
+  UINTN                                        NumberOfPages;
+  EFI_PHYSICAL_ADDRESS                         HostAddress;
+  EFI_PHYSICAL_ADDRESS                         MappedHostAddress;
+} MAP_INFO;
+
+typedef struct {
+  ACPI_HID_DEVICE_PATH        AcpiDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL    EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+typedef struct {
+  UINT64    BusBase;
+  UINT64    BusLimit;
+
+  UINT64    MemBase;
+  UINT64    MemLimit;
+
+  UINT64    IoBase;
+  UINT64    IoLimit;
+} PCI_ROOT_BRIDGE_RESOURCE_APERTURE;
+
+typedef enum {
+  TypeIo = 0,
+  TypeMem32,
+  TypePMem32,
+  TypeMem64,
+  TypePMem64,
+  TypeBus,
+  TypeMax
+} PCI_RESOURCE_TYPE;
+
+typedef enum {
+  ResNone = 0,
+  ResSubmitted,
+  ResRequested,
+  ResAllocated,
+  ResStatusMax
+} RES_STATUS;
+
+typedef struct {
+  PCI_RESOURCE_TYPE    Type;
+  UINT64               Base;
+  UINT64               Length;
+  UINT64               Alignment;
+  RES_STATUS           Status;
+} PCI_RES_NODE;
+
+#define PCI_ROOT_BRIDGE_SIGNATURE  SIGNATURE_32('e', '2', 'p', 'b')
+
+typedef struct {
+  UINT32                             Signature;
+  LIST_ENTRY                         Link;
+  EFI_HANDLE                         Handle;
+  UINT64                             RootBridgeAttrib;
+  UINT64                             Attributes;
+  UINT64                             Supports;
+
+  //
+  // Specific for this memory controller: Bus, I/O, Mem
+  //
+  PCI_RES_NODE                       ResAllocNode[6];
+
+  //
+  // Addressing for Memory and I/O and Bus arrange
+  //
+  UINT64                             BusBase;
+  UINT64                             MemBase;
+  UINT64                             IoBase;
+  UINT64                             BusLimit;
+  UINT64                             MemLimit;
+  UINT64                             IoLimit;
+
+  EFI_DEVICE_PATH_PROTOCOL           *DevicePath;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    Io;
+} PCI_ROOT_BRIDGE_INSTANCE;
+
+//
+// Driver Instance Data Macros
+//
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
+  CR(a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+#define DRIVER_INSTANCE_FROM_LIST_ENTRY(a) \
+  CR(a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE)
+
+/**
+
+  Construct the Pci Root Bridge Io protocol
+
+  @param Protocol         Point to protocol instance
+  @param HostBridgeHandle Handle of host bridge
+  @param Attri            Attribute of host bridge
+  @param ResAperture      ResourceAperture for host bridge
+
+  @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
+**/
+EFI_STATUS
+RootBridgeConstructor (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    *Protocol,
+  IN EFI_HANDLE                         HostBridgeHandle,
+  IN UINT64                             Attri,
+  IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE  *ResAperture
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.uni b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.uni
new file mode 100644
index 0000000000000000000000000000000000000000..311a1c450d0faa5317ad3b254390f866e813e712
GIT binary patch
literal 1290
zcmdUt-%A2P5Xa{^=zm!BrJ_@d9wH*r3=;Ywo<VO>cWMWE#@#9O&sU$B+|wW<=%qOJ
zc6WAX=JTDMx7WJV#W8mHoSe!~5*f=tHe~~=o^@m*&t{uoPo<CtMj}(zj{lH<S0XGI
z>~hXplCg_r#QmDgxR<QN>&p{%Cy&I*If+;&7I%Q(5NpJFZr1NI7i4qXb`~Win{w-J
zz}mAa+Zh^MN#{QCIXIPej#mb)*X?JA_Z0mvc54KCL98vT+symYU>vY&5@!xgYV<Ld
zE7O)4Wt-@8+pDr&PCIt9W}ain-Aa7bp5dWNG9!y2JBGU_Cne!JvZy3$$RUvehH~z~
z=`$BZ)|{#>L!JJYulgIRW!*w5-<CV_UoMoVrYJyrOn&X8#QIHD9zoNR5RU-b0J1Se
zvxP_3=stXW20uIN-MZC9Z91y>6-3p(8WA~^KDE2&O>W3=3(+~dre)NVCi(i@TlZCs
zMq|w&(Y|)3ARt!Ax`OxL?dnQdo1fLCO?5&l(&MGNDC<zQ>o05bzw1)t-F(Nq10q7q
A8~^|S

literal 0
HcmV?d00001

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
new file mode 100644
index 0000000000..05eec84d7e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -0,0 +1,54 @@
+## @file
+# Platform Boot Manager Lib Module
+#  The basic interfaces implementation to a single segment PCI Host Bridge
+#  driver.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PciHostBridge
+  MODULE_UNI_FILE                = PciHostBridge.uni
+  FILE_GUID                      = ACAB2797-6602-4B27-925F-B43483C630CE
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = InitializePciHostBridge
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  DxeServicesTableLib
+  UefiLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  BaseLib
+  DebugLib
+  DevicePathLib
+  IoLib
+  PciLib
+
+[Sources]
+  PciHostBridge.c
+  PciRootBridgeIo.c
+  PciHostBridge.h
+  IoFifo.h
+
+[Protocols]
+  gEfiPciHostBridgeResourceAllocationProtocolGuid       ## PRODUCES
+  gEfiPciRootBridgeIoProtocolGuid                       ## PRODUCES
+  gEfiMetronomeArchProtocolGuid                         ## CONSUMES
+  gEfiDevicePathProtocolGuid                            ## PRODUCES
+
+[depex]
+  gEfiMetronomeArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  PciHostBridgeExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeExtra.uni
new file mode 100644
index 0000000000000000000000000000000000000000..819a077f54064dbbd5e260aaecdb4615149eee47
GIT binary patch
literal 826
zcmbu7+e-pb5XQgfp#R}uFBPd}Jw-(6E+k}$Yv7y6dTGHM>xJr%uYPmZRfBqpWzOuG
zIrGgom#@#V%5umlpVOU&N;K9$hdRJ&zPcuwd)oy2R7>@cL^J*!=a93h7|R2<1-`0M
zZheh-AL<QDN=!*BB9cAizoVQU!HS6*6Y&8~pDd9_N<bNr$KjoNd(CrMZrJ6_bM0jQ
zx!ygikzPS@I>vf}uIL=O;_n`;wa1J%`5NSoiJIXJu&w=lK<+avb+X4)Wsze(w})@+
zQX&>eN}Ta8>4wg<bi3Dq-<ic*W*55L=Cb-Mi^ZhWW9M!X|KYLgRKz3$byTGPR=dsH
zYA8}|-`{NVwj);8HEgO(CBR=nYVhkZ<t(D<*<~A(XUMhl`&RayFq_E{akeShd~Moo
zy48hIOV6Akx($yIPgf0WfnMMla(iM14gNA5V_`e8LfZ~H&%DU%$iFCnRs+dxH`eOd
T?W|3^1Da{G+Wb-#ez5%pMNWT>

literal 0
HcmV?d00001

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
new file mode 100644
index 0000000000..b70e4745cc
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -0,0 +1,2421 @@
+/** @file
+  Implementation of PciRootBridgeIo.c
+  PCI Root Bridge Io Protocol implementation
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciHostBridge.h"
+#include "IoFifo.h"
+
+typedef struct {
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR    SpaceDesp[TypeMax];
+  EFI_ACPI_END_TAG_DESCRIPTOR          EndDesp;
+} RESOURCE_CONFIGURATION;
+
+RESOURCE_CONFIGURATION  Configuration = {
+  {
+    { 0x8A, 0x2B, 1, 0, 0, 0,  0, 0, 0, 0 },
+    { 0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0 },
+    { 0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0 },
+    { 0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0 },
+    { 0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0 },
+    { 0x8A, 0x2B, 2, 0, 0, 0,  0, 0, 0, 0 }
+  },
+  { 0x79, 0 }
+};
+
+//
+// Protocol Member Function Prototypes
+//
+
+/**
+  Polls an address in memory mapped I/O space until an exit condition is met,
+  or a timeout occurs.
+
+  This function provides a standard way to poll a PCI memory location. A PCI
+  memory read operation is performed at the PCI memory address specified by
+  Address for the width specified by Width. The result of this PCI memory read
+  operation is stored in Result. This PCI memory read operation is repeated
+  until either a timeout of Delay 100 ns units has expired, or (Result & Mask)
+  is equal to Value.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operations.
+  @param[in]   Address   The base address of the memory operations. The caller
+                         is responsible for aligning Address if required.
+  @param[in]   Mask      Mask used for the polling criteria. Bytes above Width
+                         in Mask are ignored. The bits in the bytes below Width
+                         which are zero in Mask are ignored when polling the
+                         memory address.
+  @param[in]   Value     The comparison value used for the polling exit
+                         criteria.
+  @param[in]   Delay     The number of 100 ns units to poll. Note that timer
+                         available may be of poorer granularity.
+  @param[out]  Result    Pointer to the last value read from the memory
+                         location.
+
+  @retval EFI_SUCCESS            The last data returned from the access matched
+                                 the poll exit criteria.
+  @retval EFI_INVALID_PARAMETER  Width is invalid.
+  @retval EFI_INVALID_PARAMETER  Result is NULL.
+  @retval EFI_TIMEOUT            Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  );
+
+/**
+  Reads from the I/O space of a PCI Root Bridge. Returns when either the
+  polling exit criteria is satisfied or after a defined duration.
+
+  This function provides a standard way to poll a PCI I/O location. A PCI I/O
+  read operation is performed at the PCI I/O address specified by Address for
+  the width specified by Width. The result of this PCI I/O read operation is
+  stored in Result. This PCI I/O read operation is repeated until either a
+  timeout of Delay 100 ns units has expired, or (Result & Mask) is equal to
+  Value.
+
+  @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in] Width     Signifies the width of the I/O operations.
+  @param[in] Address   The base address of the I/O operations. The caller is
+                       responsible for aligning Address if required.
+  @param[in] Mask      Mask used for the polling criteria. Bytes above Width in
+                       Mask are ignored. The bits in the bytes below Width
+                       which are zero in Mask are ignored when polling the I/O
+                       address.
+  @param[in] Value     The comparison value used for the polling exit criteria.
+  @param[in] Delay     The number of 100 ns units to poll. Note that timer
+                       available may be of poorer granularity.
+  @param[out] Result   Pointer to the last value read from the memory location.
+
+  @retval EFI_SUCCESS            The last data returned from the access matched
+                                 the poll exit criteria.
+  @retval EFI_INVALID_PARAMETER  Width is invalid.
+  @retval EFI_INVALID_PARAMETER  Result is NULL.
+  @retval EFI_TIMEOUT            Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  );
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge memory space.
+
+  The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+  controller registers in the PCI root bridge memory space.
+  The memory operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and memory width restrictions that a
+  PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operation.
+  @param[in]   Address   The base address of the memory operation. The caller
+                         is responsible for aligning the Address if required.
+  @param[in]   Count     The number of memory operations to perform. Bytes
+                         moved is Width size * Count, starting at Address.
+  @param[out]  Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  OUT    VOID                                   *Buffer
+  );
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge memory space.
+
+  The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+  controller registers in the PCI root bridge memory space.
+  The memory operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and memory width restrictions that a
+  PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operation.
+  @param[in]   Address   The base address of the memory operation. The caller
+                         is responsible for aligning the Address if required.
+  @param[in]   Count     The number of memory operations to perform. Bytes
+                         moved is Width size * Count, starting at Address.
+  @param[in]   Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN     VOID                                   *Buffer
+  );
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge I/O space.
+
+  @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width       Signifies the width of the memory operations.
+  @param[in]   UserAddress The base address of the I/O operation. The caller is
+                           responsible for aligning the Address if required.
+  @param[in]   Count       The number of I/O operations to perform. Bytes moved
+                           is Width size * Count, starting at Address.
+  @param[out]  UserBuffer  For read operations, the destination buffer to store
+                           the results. For write operations, the source buffer
+                           to write data from.
+
+
+  @retval EFI_SUCCESS              The data was read from or written to the PCI
+                                   root bridge.
+  @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER    Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a
+                                   lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  OUT    VOID                                   *UserBuffer
+  );
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge I/O space.
+
+  @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width       Signifies the width of the memory operations.
+  @param[in]   UserAddress The base address of the I/O operation. The caller is
+                           responsible for aligning the Address if required.
+  @param[in]   Count       The number of I/O operations to perform. Bytes moved
+                           is Width size * Count, starting at Address.
+  @param[in]   UserBuffer  For read operations, the destination buffer to store
+                           the results. For write operations, the source buffer
+                           to write data from.
+
+
+  @retval EFI_SUCCESS              The data was read from or written to the PCI
+                                   root bridge.
+  @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER    Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a
+                                   lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 UserAddress,
+  IN     UINTN                                  Count,
+  IN     VOID                                   *UserBuffer
+  );
+
+/**
+  Enables a PCI driver to copy one region of PCI root bridge memory space to
+  another region of PCI root bridge memory space.
+
+  The CopyMem() function enables a PCI driver to copy one region of PCI root
+  bridge memory space to another region of PCI root bridge memory space. This
+  is especially useful for video scroll operation on a memory mapped video
+  buffer.
+  The memory operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and memory width restrictions that a
+  PCI root bridge on a platform might require.
+
+  @param[in] This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+                         instance.
+  @param[in] Width       Signifies the width of the memory operations.
+  @param[in] DestAddress The destination address of the memory operation. The
+                         caller is responsible for aligning the DestAddress if
+                         required.
+  @param[in] SrcAddress  The source address of the memory operation. The caller
+                         is responsible for aligning the SrcAddress if
+                         required.
+  @param[in] Count       The number of memory operations to perform. Bytes
+                         moved is Width size * Count, starting at DestAddress
+                         and SrcAddress.
+
+
+  @retval  EFI_SUCCESS             The data was copied from one memory region
+                                   to another memory region.
+  @retval  EFI_INVALID_PARAMETER   Width is invalid for this PCI root bridge.
+  @retval  EFI_OUT_OF_RESOURCES    The request could not be completed due to a
+                                   lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 DestAddress,
+  IN     UINT64                                 SrcAddress,
+  IN     UINTN                                  Count
+  );
+
+/**
+  Enables a PCI driver to access PCI controller registers in a PCI root
+  bridge's configuration space.
+
+  The Pci.Read() and Pci.Write() functions enable a driver to access PCI
+  configuration registers for a PCI controller.
+  The PCI Configuration operations are carried out exactly as requested. The
+  caller is responsible for any alignment and PCI configuration width issues
+  that a PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operations.
+  @param[in]   Address   The address within the PCI configuration space for the
+                         PCI controller.
+  @param[in]   Count     The number of PCI configuration operations to perform.
+                         Bytes moved is Width size * Count, starting at
+                         Address.
+  @param[out]  Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  OUT    VOID                                   *Buffer
+  );
+
+/**
+  Enables a PCI driver to access PCI controller registers in a PCI root
+  bridge's configuration space.
+
+  The Pci.Read() and Pci.Write() functions enable a driver to access PCI
+  configuration registers for a PCI controller.
+  The PCI Configuration operations are carried out exactly as requested. The
+  caller is responsible for any alignment and PCI configuration width issues
+  that a PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operations.
+  @param[in]   Address   The address within the PCI configuration space for the
+                         PCI controller.
+  @param[in]   Count     The number of PCI configuration operations to perform.
+                         Bytes moved is Width size * Count, starting at
+                         Address.
+  @param[in]   Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN     VOID                                   *Buffer
+  );
+
+/**
+  Provides the PCI controller-specific addresses required to access system
+  memory from a DMA bus master.
+
+  The Map() function provides the PCI controller specific addresses needed to
+  access system memory. This function is used to map system memory for PCI bus
+  master DMA accesses.
+
+  @param[in]       This            A pointer to the
+                                   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]       Operation       Indicates if the bus master is going to read
+                                   or write to system memory.
+  @param[in]       HostAddress     The system memory address to map to the PCI
+                                   controller.
+  @param[in, out]  NumberOfBytes   On input the number of bytes to map. On
+                                   output the number of bytes that were mapped.
+  @param[out]      DeviceAddress   The resulting map address for the bus master
+                                   PCI controller to use to access the system
+                                   memory's HostAddress.
+  @param[out]      Mapping         The value to pass to Unmap() when the bus
+                                   master DMA operation is complete.
+
+  @retval EFI_SUCCESS            The range was mapped for the returned
+                                 NumberOfBytes.
+  @retval EFI_INVALID_PARAMETER  Operation is invalid.
+  @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
+  @retval EFI_INVALID_PARAMETER  NumberOfBytes is NULL.
+  @retval EFI_INVALID_PARAMETER  DeviceAddress is NULL.
+  @retval EFI_INVALID_PARAMETER  Mapping is NULL.
+  @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common
+                                 buffer.
+  @retval EFI_DEVICE_ERROR       The system hardware could not map the
+                                 requested address.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                                       *HostAddress,
+  IN OUT UINTN                                      *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
+  OUT    VOID                                       **Mapping
+  );
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  The Unmap() function completes the Map() operation and releases any
+  corresponding resources.
+  If the operation was an EfiPciOperationBusMasterWrite or
+  EfiPciOperationBusMasterWrite64, the data is committed to the target system
+  memory.
+  Any resources used for the mapping are freed.
+
+  @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in] Mapping   The mapping value returned from Map().
+
+  @retval EFI_SUCCESS            The range was unmapped.
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by
+                                 Map().
+  @retval EFI_DEVICE_ERROR       The data was not committed to the target
+                                 system memory.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  VOID                             *Mapping
+  );
+
+/**
+  Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer
+  or EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Type        This parameter is not used and must be ignored.
+  @param MemoryType  The type of memory to allocate, EfiBootServicesData or
+                     EfiRuntimeServicesData.
+  @param Pages       The number of pages to allocate.
+  @param HostAddress A pointer to store the base system memory address of the
+                     allocated range.
+  @param Attributes  The requested bit mask of attributes for the allocated
+                     range. Only the attributes
+                     EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
+                     EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and
+                     EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this
+                     function.
+
+  @retval EFI_SUCCESS            The requested memory pages were allocated.
+  @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
+  @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
+  @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal
+                                 attribute bits are MEMORY_WRITE_COMBINE,
+                                 MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+  @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  EFI_ALLOCATE_TYPE                Type,
+  IN  EFI_MEMORY_TYPE                  MemoryType,
+  IN  UINTN                            Pages,
+  OUT VOID                             **HostAddress,
+  IN  UINT64                           Attributes
+  );
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  The FreeBuffer() function frees memory that was allocated with
+  AllocateBuffer().
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Pages       The number of pages to free.
+  @param HostAddress The base system memory address of the allocated range.
+
+  @retval EFI_SUCCESS            The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER  The memory range specified by HostAddress and
+                                 Pages was not allocated with AllocateBuffer().
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  UINTN                            Pages,
+  OUT VOID                             *HostAddress
+  );
+
+/**
+  Flushes all PCI posted write transactions from a PCI host bridge to system
+  memory.
+
+  The Flush() function flushes any PCI posted write transactions from a PCI
+  host bridge to system memory. Posted write transactions are generated by PCI
+  bus masters when they perform write transactions to target addresses in
+  system memory.
+  This function does not flush posted write transactions from any PCI bridges.
+  A PCI controller specific action must be taken to guarantee that the posted
+  write transactions have been flushed from the PCI controller and from all the
+  PCI bridges into the PCI host bridge. This is typically done with a PCI read
+  transaction from the PCI controller prior to calling Flush().
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+  @retval EFI_SUCCESS        The PCI posted write transactions were flushed
+                             from the PCI host bridge to system memory.
+  @retval EFI_DEVICE_ERROR   The PCI posted write transactions were not flushed
+                             from the PCI host bridge due to a hardware error.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
+  );
+
+/**
+  Gets the attributes that a PCI root bridge supports setting with
+  SetAttributes(), and the attributes that a PCI root bridge is currently
+  using.
+
+  The GetAttributes() function returns the mask of attributes that this PCI
+  root bridge supports and the mask of attributes that the PCI root bridge is
+  currently using.
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Supported   A pointer to the mask of attributes that this PCI root
+                     bridge supports setting with SetAttributes().
+  @param Attributes  A pointer to the mask of attributes that this PCI root
+                     bridge is currently using.
+
+
+  @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes
+                                 that the PCI root bridge supports is returned
+                                 in Supports. If Attributes is not NULL, then
+                                 the attributes that the PCI root bridge is
+                                 currently using is returned in Attributes.
+  @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT UINT64                           *Supported,
+  OUT UINT64                           *Attributes
+  );
+
+/**
+  Sets attributes for a resource range on a PCI root bridge.
+
+  The SetAttributes() function sets the attributes specified in Attributes for
+  the PCI root bridge on the resource range specified by ResourceBase and
+  ResourceLength. Since the granularity of setting these attributes may vary
+  from resource type to resource type, and from platform to platform, the
+  actual resource range and the one passed in by the caller may differ. As a
+  result, this function may set the attributes specified by Attributes on a
+  larger resource range than the caller requested. The actual range is returned
+  in ResourceBase and ResourceLength. The caller is responsible for verifying
+  that the actual range for which the attributes were set is acceptable.
+
+  @param[in]       This            A pointer to the
+                                   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]       Attributes      The mask of attributes to set. If the
+                                   attribute bit MEMORY_WRITE_COMBINE,
+                                   MEMORY_CACHED, or MEMORY_DISABLE is set,
+                                   then the resource range is specified by
+                                   ResourceBase and ResourceLength. If
+                                   MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+                                   MEMORY_DISABLE are not set, then
+                                   ResourceBase and ResourceLength are ignored,
+                                   and may be NULL.
+
+  @param[in, out]  ResourceBase    A pointer to the base address of the
+                                   resource range to be modified by the
+                                   attributes specified by Attributes.
+  @param[in, out]  ResourceLength  A pointer to the length of the resource
+                                   range to be modified by the attributes
+                                   specified by Attributes.
+
+  @retval  EFI_SUCCESS     The current configuration of this PCI root bridge
+                           was returned in Resources.
+  @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge
+                           could not be retrieved.
+  @retval  EFI_INVALID_PARAMETER Invalid pointer of
+                                 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN     UINT64                           Attributes,
+  IN OUT UINT64                           *ResourceBase,
+  IN OUT UINT64                           *ResourceLength
+  );
+
+/**
+  Retrieves the current resource settings of this PCI root bridge in the form
+  of a set of ACPI 2.0 resource descriptors.
+
+  There are only two resource descriptor types from the ACPI Specification that
+  may be used to describe the current resources allocated to a PCI root bridge.
+  These are the QWORD Address Space Descriptor (ACPI 2.0 Section 6.4.3.5.1),
+  and the End Tag (ACPI 2.0 Section 6.4.2.8). The QWORD Address Space
+  Descriptor can describe memory, I/O, and bus number ranges for dynamic or
+  fixed resources. The configuration of a PCI root bridge is described with one
+  or more QWORD Address Space Descriptors followed by an End Tag.
+
+  @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that
+                           describe the current configuration of this PCI root
+                           bridge. The storage for the ACPI 2.0 resource
+                           descriptors is allocated by this function. The
+                           caller must treat the return buffer as read-only
+                           data, and the buffer must not be freed by the
+                           caller.
+
+  @retval  EFI_SUCCESS     The current configuration of this PCI root bridge
+                           was returned in Resources.
+  @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge
+                           could not be retrieved.
+  @retval  EFI_INVALID_PARAMETER Invalid pointer of
+                                 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT    VOID                             **Resources
+  );
+
+//
+// Memory Controller Pci Root Bridge Io Module Variables
+//
+EFI_METRONOME_ARCH_PROTOCOL  *mMetronome;
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8  mInStride[] = {
+  1, // EfiPciWidthUint8
+  2, // EfiPciWidthUint16
+  4, // EfiPciWidthUint32
+  8, // EfiPciWidthUint64
+  0, // EfiPciWidthFifoUint8
+  0, // EfiPciWidthFifoUint16
+  0, // EfiPciWidthFifoUint32
+  0, // EfiPciWidthFifoUint64
+  1, // EfiPciWidthFillUint8
+  2, // EfiPciWidthFillUint16
+  4, // EfiPciWidthFillUint32
+  8  // EfiPciWidthFillUint64
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8  mOutStride[] = {
+  1, // EfiPciWidthUint8
+  2, // EfiPciWidthUint16
+  4, // EfiPciWidthUint32
+  8, // EfiPciWidthUint64
+  1, // EfiPciWidthFifoUint8
+  2, // EfiPciWidthFifoUint16
+  4, // EfiPciWidthFifoUint32
+  8, // EfiPciWidthFifoUint64
+  0, // EfiPciWidthFillUint8
+  0, // EfiPciWidthFillUint16
+  0, // EfiPciWidthFillUint32
+  0  // EfiPciWidthFillUint64
+};
+
+/**
+  Construct the Pci Root Bridge Io protocol
+
+  @param Protocol         Point to protocol instance
+  @param HostBridgeHandle Handle of host bridge
+  @param Attri            Attribute of host bridge
+  @param ResAperture      ResourceAperture for host bridge
+
+  @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
+**/
+EFI_STATUS
+RootBridgeConstructor (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    *Protocol,
+  IN EFI_HANDLE                         HostBridgeHandle,
+  IN UINT64                             Attri,
+  IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE  *ResAperture
+  )
+{
+  EFI_STATUS                Status;
+  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+  PCI_RESOURCE_TYPE         Index;
+
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
+
+  //
+  // The host to pci bridge, the host memory and io addresses are
+  // direct mapped to pci addresses, so no need translate, set bases to 0.
+  //
+  PrivateData->MemBase = ResAperture->MemBase;
+  PrivateData->IoBase  = ResAperture->IoBase;
+
+  //
+  // The host bridge only supports 32bit addressing for memory
+  // and standard IA32 16bit io
+  //
+  PrivateData->MemLimit = ResAperture->MemLimit;
+  PrivateData->IoLimit  = ResAperture->IoLimit;
+
+  //
+  // Bus Aperture for this Root Bridge (Possible Range)
+  //
+  PrivateData->BusBase  = ResAperture->BusBase;
+  PrivateData->BusLimit = ResAperture->BusLimit;
+
+  //
+  // Specific for this chipset
+  //
+  for (Index = TypeIo; Index < TypeMax; Index++) {
+    PrivateData->ResAllocNode[Index].Type   = Index;
+    PrivateData->ResAllocNode[Index].Base   = 0;
+    PrivateData->ResAllocNode[Index].Length = 0;
+    PrivateData->ResAllocNode[Index].Status = ResNone;
+  }
+
+  PrivateData->RootBridgeAttrib = Attri;
+
+  PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
+                          EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
+                          EFI_PCI_ATTRIBUTE_ISA_IO_16 |
+                          EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO |
+                          EFI_PCI_ATTRIBUTE_VGA_MEMORY |
+                          EFI_PCI_ATTRIBUTE_VGA_IO_16  |
+                          EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
+  PrivateData->Attributes = PrivateData->Supports;
+
+  Protocol->ParentHandle = HostBridgeHandle;
+
+  Protocol->PollMem = RootBridgeIoPollMem;
+  Protocol->PollIo  = RootBridgeIoPollIo;
+
+  Protocol->Mem.Read  = RootBridgeIoMemRead;
+  Protocol->Mem.Write = RootBridgeIoMemWrite;
+
+  Protocol->Io.Read  = RootBridgeIoIoRead;
+  Protocol->Io.Write = RootBridgeIoIoWrite;
+
+  Protocol->CopyMem = RootBridgeIoCopyMem;
+
+  Protocol->Pci.Read  = RootBridgeIoPciRead;
+  Protocol->Pci.Write = RootBridgeIoPciWrite;
+
+  Protocol->Map   = RootBridgeIoMap;
+  Protocol->Unmap = RootBridgeIoUnmap;
+
+  Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
+  Protocol->FreeBuffer     = RootBridgeIoFreeBuffer;
+
+  Protocol->Flush = RootBridgeIoFlush;
+
+  Protocol->GetAttributes = RootBridgeIoGetAttributes;
+  Protocol->SetAttributes = RootBridgeIoSetAttributes;
+
+  Protocol->Configuration = RootBridgeIoConfiguration;
+
+  Protocol->SegmentNumber = 0;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiMetronomeArchProtocolGuid,
+                  NULL,
+                  (VOID **)&mMetronome
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
+
+  The I/O operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and I/O width restrictions that a PI
+  System on a platform might require. For example on some platforms, width
+  requests of EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other
+  hand, will be handled by the driver.
+
+  @param[in] This           A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in] OperationType  I/O operation type: IO/MMIO/PCI.
+  @param[in] Width          Signifies the width of the I/O or Memory operation.
+  @param[in] Address        The base address of the I/O operation.
+  @param[in] Count          The number of I/O operations to perform. The number
+                            of bytes moved is Width size * Count, starting at
+                            Address.
+  @param[in] Buffer         For read operations, the destination buffer to
+                            store the results. For write operations, the source
+                            buffer from which to write data.
+
+  @retval EFI_SUCCESS            The parameters for this request pass the
+                                 checks.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
+  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
+                                 and Count is not valid for this PI system.
+**/
+EFI_STATUS
+RootBridgeIoCheckParameter (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN OPERATION_TYPE                         OperationType,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 Address,
+  IN UINTN                                  Count,
+  IN VOID                                   *Buffer
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE                     *PrivateData;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  *PciRbAddr;
+  UINT64                                       MaxCount;
+  UINT64                                       Base;
+  UINT64                                       Limit;
+
+  //
+  // Check to see if Buffer is NULL
+  //
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check to see if Width is in the valid range
+  //
+  if ((UINT32)Width >= EfiPciWidthMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // For FIFO type, the target address won't increase during the access,
+  // so treat Count as 1
+  //
+  if ((Width >= EfiPciWidthFifoUint8) && (Width <= EfiPciWidthFifoUint64)) {
+    Count = 1;
+  }
+
+  //
+  // Check to see if Width is in the valid range for I/O Port operations
+  //
+  Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
+  if ((OperationType != MemOperation) && (Width == EfiPciWidthUint64)) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check to see if Address is aligned
+  //
+  if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+  //
+  // Check to see if any address associated with this transfer exceeds the
+  // maximum allowed address.  The maximum address implied by the parameters
+  // passed in is Address + Size * Count.  If the following condition is met,
+  // then the transfer is not supported.
+  //
+  //    Address + Size * Count > Limit + 1
+  //
+  // Since Limit can be the maximum integer value supported by the CPU and
+  // Count can also be the maximum integer value supported by the CPU, this
+  // range check must be adjusted to avoid all oveflow conditions.
+  //
+  // The following form of the range check is equivalent but assumes that
+  // Limit is of the form (2^n - 1).
+  //
+  if (OperationType == IoOperation) {
+    Base  = PrivateData->IoBase;
+    Limit = PrivateData->IoLimit;
+  } else if (OperationType == MemOperation) {
+    Base  = PrivateData->MemBase;
+    Limit = PrivateData->MemLimit;
+  } else {
+    PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&Address;
+    if ((PciRbAddr->Bus < PrivateData->BusBase) ||
+        (PciRbAddr->Bus > PrivateData->BusLimit))
+    {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if ((PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER) ||
+        (PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER))
+    {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (PciRbAddr->ExtendedRegister != 0) {
+      Address = PciRbAddr->ExtendedRegister;
+    } else {
+      Address = PciRbAddr->Register;
+    }
+
+    Base  = 0;
+    Limit = MAX_PCI_REG_ADDRESS;
+  }
+
+  if (Address < Base) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Count == 0) {
+    if (Address > Limit) {
+      return EFI_UNSUPPORTED;
+    }
+  } else {
+    MaxCount = RShiftU64 (Limit, Width);
+    if (MaxCount < (Count - 1)) {
+      return EFI_UNSUPPORTED;
+    }
+
+    if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Internal help function for read and write memory space.
+
+  @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Write         Switch value for Read or Write.
+  @param[in]   Width         Signifies the width of the memory operations.
+  @param[in]   UserAddress   The address within the PCI configuration space for
+                             the PCI controller.
+  @param[in]   Count         The number of PCI configuration operations to
+                             perform. Bytes moved is Width size * Count,
+                             starting at Address.
+  @param[in, out] UserBuffer For read operations, the destination buffer to
+                             store the results. For write operations, the
+                             source buffer to write data from.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+RootBridgeIoMemRW (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     BOOLEAN                                Write,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+{
+  EFI_STATUS                             Status;
+  UINT8                                  InStride;
+  UINT8                                  OutStride;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  OperationWidth;
+  UINT8                                  *Uint8Buffer;
+
+  Status = RootBridgeIoCheckParameter (
+             This,
+             MemOperation,
+             Width,
+             Address,
+             Count,
+             Buffer
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  InStride       = mInStride[Width];
+  OutStride      = mOutStride[Width];
+  OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
+  for (Uint8Buffer = Buffer;
+       Count > 0;
+       Address += InStride, Uint8Buffer += OutStride, Count--)
+  {
+    if (Write) {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+          break;
+        case EfiPciWidthUint16:
+          MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+          break;
+        case EfiPciWidthUint32:
+          MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+          break;
+        case EfiPciWidthUint64:
+          MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+          break;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    } else {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          *Uint8Buffer = MmioRead8 ((UINTN)Address);
+          break;
+        case EfiPciWidthUint16:
+          *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+          break;
+        case EfiPciWidthUint32:
+          *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+          break;
+        case EfiPciWidthUint64:
+          *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+          break;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Internal help function for read and write IO space.
+
+  @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Write         Switch value for Read or Write.
+  @param[in]   Width         Signifies the width of the memory operations.
+  @param[in]   UserAddress   The address within the PCI configuration space for
+                             the PCI controller.
+  @param[in]   Count         The number of PCI configuration operations to
+                             perform. Bytes moved is Width size * Count,
+                             starting at Address.
+  @param[in, out] UserBuffer For read operations, the destination buffer to
+                             store the results. For write operations, the
+                             source buffer to write data from.
+
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+RootBridgeIoIoRW (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     BOOLEAN                                Write,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN OUT VOID                                   *Buffer
+  )
+{
+  EFI_STATUS                             Status;
+  UINT8                                  InStride;
+  UINT8                                  OutStride;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  OperationWidth;
+  UINT8                                  *Uint8Buffer;
+
+  Status = RootBridgeIoCheckParameter (
+             This,
+             IoOperation,
+             Width,
+             Address,
+             Count,
+             Buffer
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  InStride       = mInStride[Width];
+  OutStride      = mOutStride[Width];
+  OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
+
+ #if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
+  if (InStride == 0) {
+    if (Write) {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          IoWriteFifo8 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        case EfiPciWidthUint16:
+          IoWriteFifo16 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        case EfiPciWidthUint32:
+          IoWriteFifo32 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    } else {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          IoReadFifo8 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        case EfiPciWidthUint16:
+          IoReadFifo16 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        case EfiPciWidthUint32:
+          IoReadFifo32 ((UINTN)Address, Count, Buffer);
+          return EFI_SUCCESS;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    }
+  }
+
+ #endif
+
+  for (Uint8Buffer = Buffer;
+       Count > 0;
+       Address += InStride, Uint8Buffer += OutStride, Count--)
+  {
+    if (Write) {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          IoWrite8 ((UINTN)Address, *Uint8Buffer);
+          break;
+        case EfiPciWidthUint16:
+          IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+          break;
+        case EfiPciWidthUint32:
+          IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+          break;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    } else {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          *Uint8Buffer = IoRead8 ((UINTN)Address);
+          break;
+        case EfiPciWidthUint16:
+          *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
+          break;
+        case EfiPciWidthUint32:
+          *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
+          break;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Internal help function for read and write PCI configuration space.
+
+  @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Write         Switch value for Read or Write.
+  @param[in]   Width         Signifies the width of the memory operations.
+  @param[in]   UserAddress   The address within the PCI configuration space for
+                             the PCI controller.
+  @param[in]   Count         The number of PCI configuration operations to
+                             perform. Bytes moved is Width size * Count,
+                             starting at Address.
+  @param[in, out] UserBuffer For read operations, the destination buffer to
+                             store the results. For write operations, the
+                             source buffer to write data from.
+
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+RootBridgeIoPciRW (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN BOOLEAN                                Write,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 Address,
+  IN UINTN                                  Count,
+  IN OUT VOID                               *Buffer
+  )
+{
+  EFI_STATUS                                   Status;
+  UINT8                                        InStride;
+  UINT8                                        OutStride;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH        OperationWidth;
+  UINT8                                        *Uint8Buffer;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  *PciRbAddr;
+  UINTN                                        PcieRegAddr;
+
+  Status = RootBridgeIoCheckParameter (
+             This,
+             PciOperation,
+             Width,
+             Address,
+             Count,
+             Buffer
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *)&Address;
+
+  PcieRegAddr = (UINTN)PCI_LIB_ADDRESS (
+                         PciRbAddr->Bus,
+                         PciRbAddr->Device,
+                         PciRbAddr->Function,
+                         (PciRbAddr->ExtendedRegister != 0) ? \
+                         PciRbAddr->ExtendedRegister :
+                         PciRbAddr->Register
+                         );
+
+  InStride       = mInStride[Width];
+  OutStride      = mOutStride[Width];
+  OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03);
+  for (Uint8Buffer = Buffer;
+       Count > 0;
+       PcieRegAddr += InStride, Uint8Buffer += OutStride, Count--)
+  {
+    if (Write) {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          PciWrite8 (PcieRegAddr, *Uint8Buffer);
+          break;
+        case EfiPciWidthUint16:
+          PciWrite16 (PcieRegAddr, *((UINT16 *)Uint8Buffer));
+          break;
+        case EfiPciWidthUint32:
+          PciWrite32 (PcieRegAddr, *((UINT32 *)Uint8Buffer));
+          break;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    } else {
+      switch (OperationWidth) {
+        case EfiPciWidthUint8:
+          *Uint8Buffer = PciRead8 (PcieRegAddr);
+          break;
+        case EfiPciWidthUint16:
+          *((UINT16 *)Uint8Buffer) = PciRead16 (PcieRegAddr);
+          break;
+        case EfiPciWidthUint32:
+          *((UINT32 *)Uint8Buffer) = PciRead32 (PcieRegAddr);
+          break;
+        default:
+          //
+          // The RootBridgeIoCheckParameter call above will ensure that this
+          // path is not taken.
+          //
+          ASSERT (FALSE);
+          break;
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Polls an address in memory mapped I/O space until an exit condition is met,
+  or a timeout occurs.
+
+  This function provides a standard way to poll a PCI memory location. A PCI
+  memory read operation is performed at the PCI memory address specified by
+  Address for the width specified by Width. The result of this PCI memory read
+  operation is stored in Result. This PCI memory read operation is repeated
+  until either a timeout of Delay 100 ns units has expired, or (Result & Mask)
+  is equal to Value.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operations.
+  @param[in]   Address   The base address of the memory operations. The caller
+                         is responsible for aligning Address if required.
+  @param[in]   Mask      Mask used for the polling criteria. Bytes above Width
+                         in Mask are ignored. The bits in the bytes below Width
+                         which are zero in Mask are ignored when polling the
+                         memory address.
+  @param[in]   Value     The comparison value used for the polling exit
+                         criteria.
+  @param[in]   Delay     The number of 100 ns units to poll. Note that timer
+                         available may be of poorer granularity.
+  @param[out]  Result    Pointer to the last value read from the memory
+                         location.
+
+  @retval EFI_SUCCESS            The last data returned from the access matched
+                                 the poll exit criteria.
+  @retval EFI_INVALID_PARAMETER  Width is invalid.
+  @retval EFI_INVALID_PARAMETER  Result is NULL.
+  @retval EFI_TIMEOUT            Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      NumberOfTicks;
+  UINT32      Remainder;
+
+  if (Result == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((UINT32)Width > EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // No matter what, always do a single poll.
+  //
+  Status = This->Mem.Read (This, Width, Address, 1, Result);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if ((*Result & Mask) == Value) {
+    return EFI_SUCCESS;
+  }
+
+  if (Delay == 0) {
+    return EFI_SUCCESS;
+  } else {
+    //
+    // Determine the proper # of metronome ticks to wait for polling the
+    // location.  The nuber of ticks is Roundup (Delay /
+    // mMetronome->TickPeriod)+1
+    // The "+1" to account for the possibility of the first tick being short
+    // because we started in the middle of a tick.
+    //
+    // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
+    // protocol definition is updated.
+    //
+    NumberOfTicks = DivU64x32Remainder (
+                      Delay,
+                      (UINT32)mMetronome->TickPeriod,
+                      &Remainder
+                      );
+    if (Remainder != 0) {
+      NumberOfTicks += 1;
+    }
+
+    NumberOfTicks += 1;
+
+    while (NumberOfTicks != 0) {
+      mMetronome->WaitForTick (mMetronome, 1);
+
+      Status = This->Mem.Read (This, Width, Address, 1, Result);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      if ((*Result & Mask) == Value) {
+        return EFI_SUCCESS;
+      }
+
+      NumberOfTicks -= 1;
+    }
+  }
+
+  return EFI_TIMEOUT;
+}
+
+/**
+  Reads from the I/O space of a PCI Root Bridge. Returns when either the
+  polling exit criteria is satisfied or after a defined duration.
+
+  This function provides a standard way to poll a PCI I/O location. A PCI I/O
+  read operation is performed at the PCI I/O address specified by Address for
+  the width specified by Width.
+  The result of this PCI I/O read operation is stored in Result. This PCI I/O
+  read operation is repeated until either a timeout of Delay 100 ns units has
+  expired, or (Result & Mask) is equal to Value.
+
+  @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in] Width     Signifies the width of the I/O operations.
+  @param[in] Address   The base address of the I/O operations. The caller is
+                       responsible for aligning Address if required.
+  @param[in] Mask      Mask used for the polling criteria. Bytes above Width in
+                       Mask are ignored. The bits in the bytes below Width
+                       which are zero in Mask are ignored when polling the I/O
+                       address.
+  @param[in] Value     The comparison value used for the polling exit criteria.
+  @param[in] Delay     The number of 100 ns units to poll. Note that timer
+                       available may be of poorer granularity.
+  @param[out] Result   Pointer to the last value read from the memory location.
+
+  @retval EFI_SUCCESS            The last data returned from the access matched
+                                 the poll exit criteria.
+  @retval EFI_INVALID_PARAMETER  Width is invalid.
+  @retval EFI_INVALID_PARAMETER  Result is NULL.
+  @retval EFI_TIMEOUT            Delay expired before a match occurred.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN  UINT64                                 Address,
+  IN  UINT64                                 Mask,
+  IN  UINT64                                 Value,
+  IN  UINT64                                 Delay,
+  OUT UINT64                                 *Result
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      NumberOfTicks;
+  UINT32      Remainder;
+
+  //
+  // No matter what, always do a single poll.
+  //
+
+  if (Result == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((UINT32)Width > EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = This->Io.Read (This, Width, Address, 1, Result);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if ((*Result & Mask) == Value) {
+    return EFI_SUCCESS;
+  }
+
+  if (Delay == 0) {
+    return EFI_SUCCESS;
+  } else {
+    //
+    // Determine the proper # of metronome ticks to wait for polling the
+    // location.  The number of ticks is Roundup (Delay /
+    // mMetronome->TickPeriod)+1
+    // The "+1" to account for the possibility of the first tick being short
+    // because we started in the middle of a tick.
+    //
+    NumberOfTicks = DivU64x32Remainder (
+                      Delay,
+                      (UINT32)mMetronome->TickPeriod,
+                      &Remainder
+                      );
+    if (Remainder != 0) {
+      NumberOfTicks += 1;
+    }
+
+    NumberOfTicks += 1;
+
+    while (NumberOfTicks != 0) {
+      mMetronome->WaitForTick (mMetronome, 1);
+
+      Status = This->Io.Read (This, Width, Address, 1, Result);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      if ((*Result & Mask) == Value) {
+        return EFI_SUCCESS;
+      }
+
+      NumberOfTicks -= 1;
+    }
+  }
+
+  return EFI_TIMEOUT;
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge memory space.
+
+  The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+  controller registers in the PCI root bridge memory space.
+  The memory operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and memory width restrictions that a
+  PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operation.
+  @param[in]   Address   The base address of the memory operation. The caller
+                         is responsible for aligning the Address if required.
+  @param[in]   Count     The number of memory operations to perform. Bytes
+                         moved is Width size * Count, starting at Address.
+  @param[out]  Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  OUT    VOID                                   *Buffer
+  )
+{
+  return RootBridgeIoMemRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge memory space.
+
+  The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
+  controller registers in the PCI root bridge memory space.
+  The memory operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and memory width restrictions that a
+  PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operation.
+  @param[in]   Address   The base address of the memory operation. The caller
+                         is responsible for aligning the Address if required.
+  @param[in]   Count     The number of memory operations to perform. Bytes
+                         moved is Width size * Count, starting at Address.
+  @param[in]   Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  IN     VOID                                   *Buffer
+  )
+{
+  return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge I/O space.
+
+  @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width       Signifies the width of the memory operations.
+  @param[in]   Address     The base address of the I/O operation. The caller is
+                           responsible for aligning the Address if required.
+  @param[in]   Count       The number of I/O operations to perform. Bytes moved
+                           is Width size * Count, starting at Address.
+  @param[out]  Buffer      For read operations, the destination buffer to store
+                           the results. For write operations, the source buffer
+                           to write data from.
+
+
+  @retval EFI_SUCCESS              The data was read from or written to the PCI
+                                   root bridge.
+  @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER    Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a
+                                   lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN     UINT64                                 Address,
+  IN     UINTN                                  Count,
+  OUT    VOID                                   *Buffer
+  )
+{
+  return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in the PCI root
+  bridge I/O space.
+
+  @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width       Signifies the width of the memory operations.
+  @param[in]   Address     The base address of the I/O operation. The caller is
+                           responsible for aligning the Address if required.
+  @param[in]   Count       The number of I/O operations to perform. Bytes moved
+                           is Width size * Count, starting at Address.
+  @param[in]   Buffer      For read operations, the destination buffer to store
+                           the results. For write operations, the source buffer
+                           to write data from.
+
+  @retval EFI_SUCCESS              The data was read from or written to the PCI
+                                   root bridge.
+  @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER    Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a
+                                   lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN       UINT64                                 Address,
+  IN       UINTN                                  Count,
+  IN       VOID                                   *Buffer
+  )
+{
+  return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+  Enables a PCI driver to copy one region of PCI root bridge memory space to
+  another region of PCI root bridge memory space.
+
+  The CopyMem() function enables a PCI driver to copy one region of PCI root
+  bridge memory space to another region of PCI root bridge memory space. This
+  is especially useful for video scroll operation on a memory mapped video
+  buffer.
+  The memory operations are carried out exactly as requested. The caller is
+  responsible for satisfying any alignment and memory width restrictions that a
+  PCI root bridge on a platform might require.
+
+  @param[in] This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+                         instance.
+  @param[in] Width       Signifies the width of the memory operations.
+  @param[in] DestAddress The destination address of the memory operation. The
+                         caller is responsible for aligning the DestAddress if
+                         required.
+  @param[in] SrcAddress  The source address of the memory operation. The caller
+                         is responsible for aligning the SrcAddress if
+                         required.
+  @param[in] Count       The number of memory operations to perform. Bytes
+                         moved is Width size * Count, starting at DestAddress
+                         and SrcAddress.
+
+  @retval  EFI_SUCCESS             The data was copied from one memory region
+                                   to another memory region.
+  @retval  EFI_INVALID_PARAMETER   Width is invalid for this PCI root bridge.
+  @retval  EFI_OUT_OF_RESOURCES    The request could not be completed due to a
+                                   lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN UINT64                                 DestAddress,
+  IN UINT64                                 SrcAddress,
+  IN UINTN                                  Count
+  )
+{
+  EFI_STATUS  Status;
+  BOOLEAN     Direction;
+  UINTN       Stride;
+  UINTN       Index;
+  UINT64      Result;
+
+  if ((UINT32)Width > EfiPciWidthUint64) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (DestAddress == SrcAddress) {
+    return EFI_SUCCESS;
+  }
+
+  Stride = (UINTN)(1 << Width);
+
+  Direction = TRUE;
+  if ((DestAddress > SrcAddress) &&
+      (DestAddress < (SrcAddress + Count * Stride)))
+  {
+    Direction   = FALSE;
+    SrcAddress  = SrcAddress  + (Count-1) * Stride;
+    DestAddress = DestAddress + (Count-1) * Stride;
+  }
+
+  for (Index = 0; Index < Count; Index++) {
+    Status = RootBridgeIoMemRead (
+               This,
+               Width,
+               SrcAddress,
+               1,
+               &Result
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Status = RootBridgeIoMemWrite (
+               This,
+               Width,
+               DestAddress,
+               1,
+               &Result
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    if (Direction) {
+      SrcAddress  += Stride;
+      DestAddress += Stride;
+    } else {
+      SrcAddress  -= Stride;
+      DestAddress -= Stride;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in a PCI root
+  bridge's configuration space.
+
+  The Pci.Read() and Pci.Write() functions enable a driver to access PCI
+  configuration registers for a PCI controller.
+  The PCI Configuration operations are carried out exactly as requested. The
+  caller is responsible for any alignment and PCI configuration width issues
+  that a PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operations.
+  @param[in]   Address   The address within the PCI configuration space for the
+                         PCI controller.
+  @param[in]   Count     The number of PCI configuration operations to perform.
+                         Bytes moved is Width size * Count, starting at
+                         Address.
+  @param[out]  Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN       UINT64                                 Address,
+  IN       UINTN                                  Count,
+  OUT      VOID                                   *Buffer
+  )
+{
+  return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+  Enables a PCI driver to access PCI controller registers in a PCI root
+  bridge's configuration space.
+
+  The Pci.Read() and Pci.Write() functions enable a driver to access PCI
+  configuration registers for a PCI controller.
+  The PCI Configuration operations are carried out exactly as requested. The
+  caller is responsible for any alignment and PCI configuration width issues
+  that a PCI Root Bridge on a platform might require.
+
+  @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]   Width     Signifies the width of the memory operations.
+  @param[in]   Address   The address within the PCI configuration space for the
+                         PCI controller.
+  @param[in]   Count     The number of PCI configuration operations to perform.
+                         Bytes moved is Width size * Count, starting at
+                         Address.
+  @param[in]   Buffer    For read operations, the destination buffer to store
+                         the results. For write operations, the source buffer
+                         to write data from.
+
+  @retval EFI_SUCCESS            The data was read from or written to the PCI
+                                 root bridge.
+  @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
+  IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
+  IN       UINT64                                 Address,
+  IN       UINTN                                  Count,
+  IN       VOID                                   *Buffer
+  )
+{
+  return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+  Provides the PCI controller-specific addresses required to access system
+  memory from a DMA bus master.
+
+  The Map() function provides the PCI controller specific addresses needed to
+  access system memory. This function is used to map system memory for PCI bus
+  master DMA accesses.
+
+  @param[in]       This            A pointer to the
+                                   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]       Operation       Indicates if the bus master is going to read
+                                   or write to system memory.
+  @param[in]       HostAddress     The system memory address to map to the PCI
+                                   controller.
+  @param[in, out]  NumberOfBytes   On input the number of bytes to map. On
+                                   output the number of bytes that were mapped.
+  @param[out]      DeviceAddress   The resulting map address for the bus master
+                                   PCI controller to use to access the system
+                                   memory's HostAddress.
+  @param[out]      Mapping         The value to pass to Unmap() when the bus
+                                   master DMA operation is complete.
+
+  @retval EFI_SUCCESS            The range was mapped for the returned
+                                 NumberOfBytes.
+  @retval EFI_INVALID_PARAMETER  Operation is invalid.
+  @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
+  @retval EFI_INVALID_PARAMETER  NumberOfBytes is NULL.
+  @retval EFI_INVALID_PARAMETER  DeviceAddress is NULL.
+  @retval EFI_INVALID_PARAMETER  Mapping is NULL.
+  @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common
+                                 buffer.
+  @retval EFI_DEVICE_ERROR       The system hardware could not map the
+                                 requested address.
+  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
+                                 lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
+  IN     VOID                                       *HostAddress,
+  IN OUT UINTN                                      *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
+  OUT    VOID                                       **Mapping
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
+  MAP_INFO              *MapInfo;
+
+  if ((HostAddress == NULL) || (NumberOfBytes == NULL) || (DeviceAddress == NULL) ||
+      (Mapping == NULL))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Initialize the return values to their defaults
+  //
+  *Mapping = NULL;
+
+  //
+  // Make sure that Operation is valid
+  //
+  if ((UINT32)Operation >= EfiPciOperationMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Most PCAT like chipsets can not handle performing DMA above 4GB.
+  // If any part of the DMA transfer being mapped is above 4GB, then
+  // map the DMA transfer to a buffer below 4GB.
+  //
+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
+  if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {
+    //
+    // Common Buffer operations can not be remapped.  If the common buffer
+    // if above 4GB, then it is not possible to generate a mapping, so return
+    // an error.
+    //
+    if ((Operation == EfiPciOperationBusMasterCommonBuffer) ||
+        (Operation == EfiPciOperationBusMasterCommonBuffer64))
+    {
+      return EFI_UNSUPPORTED;
+    }
+
+    //
+    // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+    // called later.
+    //
+    Status = gBS->AllocatePool (
+                    EfiBootServicesData,
+                    sizeof (MAP_INFO),
+                    (VOID **)&MapInfo
+                    );
+    if (EFI_ERROR (Status)) {
+      *NumberOfBytes = 0;
+      return Status;
+    }
+
+    //
+    // Return a pointer to the MAP_INFO structure in Mapping
+    //
+    *Mapping = MapInfo;
+
+    //
+    // Initialize the MAP_INFO structure
+    //
+    MapInfo->Operation         = Operation;
+    MapInfo->NumberOfBytes     = *NumberOfBytes;
+    MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES (*NumberOfBytes);
+    MapInfo->HostAddress       = PhysicalAddress;
+    MapInfo->MappedHostAddress = 0x00000000ffffffff;
+
+    //
+    // Allocate a buffer below 4GB to map the transfer to.
+    //
+    Status = gBS->AllocatePages (
+                    AllocateMaxAddress,
+                    EfiBootServicesData,
+                    MapInfo->NumberOfPages,
+                    &MapInfo->MappedHostAddress
+                    );
+    if (EFI_ERROR (Status)) {
+      gBS->FreePool (MapInfo);
+      *NumberOfBytes = 0;
+      return Status;
+    }
+
+    //
+    // If this is a read operation from the Bus Master's point of view,
+    // then copy the contents of the real buffer into the mapped buffer
+    // so the Bus Master can read the contents of the real buffer.
+    //
+    if ((Operation == EfiPciOperationBusMasterRead) ||
+        (Operation == EfiPciOperationBusMasterRead64))
+    {
+      CopyMem (
+        (VOID *)(UINTN)MapInfo->MappedHostAddress,
+        (VOID *)(UINTN)MapInfo->HostAddress,
+        MapInfo->NumberOfBytes
+        );
+    }
+
+    //
+    // The DeviceAddress is the address of the maped buffer below 4GB
+    //
+    *DeviceAddress = MapInfo->MappedHostAddress;
+  } else {
+    //
+    // The transfer is below 4GB, so the DeviceAddress is simply the
+    // HostAddress
+    //
+    *DeviceAddress = PhysicalAddress;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  The Unmap() function completes the Map() operation and releases any
+  corresponding resources.
+  If the operation was an EfiPciOperationBusMasterWrite or
+  EfiPciOperationBusMasterWrite64, the data is committed to the target system
+  memory.
+  Any resources used for the mapping are freed.
+
+  @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in] Mapping   The mapping value returned from Map().
+
+  @retval EFI_SUCCESS            The range was unmapped.
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by
+                                 Map().
+  @retval EFI_DEVICE_ERROR       The data was not committed to the target
+                                 system memory.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN VOID                             *Mapping
+  )
+{
+  MAP_INFO  *MapInfo;
+
+  //
+  // See if the Map() operation associated with this Unmap() required a mapping
+  // buffer. If a mapping buffer was not required, then this function simply
+  // returns EFI_SUCCESS.
+  //
+  if (Mapping != NULL) {
+    //
+    // Get the MAP_INFO structure from Mapping
+    //
+    MapInfo = (MAP_INFO *)Mapping;
+
+    //
+    // If this is a write operation from the Bus Master's point of view,
+    // then copy the contents of the mapped buffer into the real buffer
+    // so the processor can read the contents of the real buffer.
+    //
+    if ((MapInfo->Operation == EfiPciOperationBusMasterWrite) ||
+        (MapInfo->Operation == EfiPciOperationBusMasterWrite64))
+    {
+      CopyMem (
+        (VOID *)(UINTN)MapInfo->HostAddress,
+        (VOID *)(UINTN)MapInfo->MappedHostAddress,
+        MapInfo->NumberOfBytes
+        );
+    }
+
+    //
+    // Free the mapped buffer and the MAP_INFO structure.
+    //
+    gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
+    gBS->FreePool (Mapping);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer
+  or EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Type        This parameter is not used and must be ignored.
+  @param MemoryType  The type of memory to allocate, EfiBootServicesData or
+                     EfiRuntimeServicesData.
+  @param Pages       The number of pages to allocate.
+  @param HostAddress A pointer to store the base system memory address of the
+                     allocated range.
+  @param Attributes  The requested bit mask of attributes for the allocated
+                     range. Only the attributes
+                     EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
+                     EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and
+                     EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this
+                     function.
+
+  @retval EFI_SUCCESS            The requested memory pages were allocated.
+  @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
+  @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
+  @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal
+                                 attribute bits are MEMORY_WRITE_COMBINE,
+                                 MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+  @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  EFI_ALLOCATE_TYPE                Type,
+  IN  EFI_MEMORY_TYPE                  MemoryType,
+  IN  UINTN                            Pages,
+  OUT VOID                             **HostAddress,
+  IN  UINT64                           Attributes
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
+
+  //
+  // Validate Attributes
+  //
+  if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check for invalid inputs
+  //
+  if (HostAddress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // The only valid memory types are EfiBootServicesData and
+  // EfiRuntimeServicesData
+  //
+  if ((MemoryType != EfiBootServicesData) &&
+      (MemoryType != EfiRuntimeServicesData))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Limit allocations to memory below 4GB
+  //
+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
+
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  MemoryType,
+                  Pages,
+                  &PhysicalAddress
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *HostAddress = (VOID *)(UINTN)PhysicalAddress;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  The FreeBuffer() function frees memory that was allocated with
+  AllocateBuffer().
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Pages       The number of pages to free.
+  @param HostAddress The base system memory address of the allocated range.
+
+  @retval EFI_SUCCESS            The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER  The memory range specified by HostAddress and
+                                 Pages was not allocated with AllocateBuffer().
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN  UINTN                            Pages,
+  OUT VOID                             *HostAddress
+  )
+{
+  return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages);
+}
+
+/**
+  Flushes all PCI posted write transactions from a PCI host bridge to system
+  memory.
+
+  The Flush() function flushes any PCI posted write transactions from a PCI
+  host bridge to system memory. Posted write transactions are generated by PCI
+  bus masters when they perform write transactions to target addresses in
+  system memory.
+  This function does not flush posted write transactions from any PCI bridges.
+  A PCI controller specific action must be taken to guarantee that the posted
+  write transactions have been flushed from the PCI controller and from all the
+  PCI bridges into the PCI host bridge. This is typically done with a PCI read
+  transaction from the PCI controller prior to calling Flush().
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+  @retval EFI_SUCCESS        The PCI posted write transactions were flushed
+                             from the PCI host bridge to system memory.
+  @retval EFI_DEVICE_ERROR   The PCI posted write transactions were not flushed
+                             from the PCI host bridge due to a hardware error.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
+  )
+{
+  //
+  // not supported yet
+  //
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the attributes that a PCI root bridge supports setting with
+  SetAttributes(), and the attributes that a PCI root bridge is currently
+  using.
+
+  The GetAttributes() function returns the mask of attributes that this PCI
+  root bridge supports and the mask of attributes that the PCI root bridge is
+  currently using.
+
+  @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Supported   A pointer to the mask of attributes that this PCI root
+                     bridge supports setting with SetAttributes().
+  @param Attributes  A pointer to the mask of attributes that this PCI root
+                     bridge is currently using.
+
+  @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes
+                                 that the PCI root bridge supports is returned
+                                 in Supports. If Attributes is not NULL, then
+                                 the attributes that the PCI root bridge is
+                                 currently using is returned in Attributes.
+  @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT UINT64                           *Supported,
+  OUT UINT64                           *Attributes
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+  if ((Attributes == NULL) && (Supported == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Set the return value for Supported and Attributes
+  //
+  if (Supported != NULL) {
+    *Supported = PrivateData->Supports;
+  }
+
+  if (Attributes != NULL) {
+    *Attributes = PrivateData->Attributes;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Sets attributes for a resource range on a PCI root bridge.
+
+  The SetAttributes() function sets the attributes specified in Attributes for
+  the PCI root bridge on the resource range specified by ResourceBase and
+  ResourceLength. Since the granularity of setting these attributes may vary
+  from resource type to resource type, and from platform to platform, the
+  actual resource range and the one passed in by the caller may differ. As a
+  result, this function may set the attributes specified by Attributes on a
+  larger resource range than the caller requested. The actual range is returned
+  in ResourceBase and ResourceLength. The caller is responsible for verifying
+  that the actual range for which the attributes were set is acceptable.
+
+  @param[in]       This            A pointer to the
+                                   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[in]       Attributes      The mask of attributes to set. If the
+                                   attribute bit MEMORY_WRITE_COMBINE,
+                                   MEMORY_CACHED, or MEMORY_DISABLE is set,
+                                   then the resource range is specified by
+                                   ResourceBase and ResourceLength. If
+                                   MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+                                   MEMORY_DISABLE are not set, then
+                                   ResourceBase and ResourceLength are ignored,
+                                   and may be NULL.
+  @param[in, out]  ResourceBase    A pointer to the base address of the
+                                   resource range to be modified by the
+                                   attributes specified by Attributes.
+  @param[in, out]  ResourceLength  A pointer to the length of the resource
+                                   range to be modified by the attributes
+                                   specified by Attributes.
+
+  @retval  EFI_SUCCESS     The current configuration of this PCI root bridge
+                           was returned in Resources.
+  @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge
+                           could not be retrieved.
+  @retval  EFI_INVALID_PARAMETER Invalid pointer of
+                                 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+  IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  IN     UINT64                           Attributes,
+  IN OUT UINT64                           *ResourceBase,
+  IN OUT UINT64                           *ResourceLength
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+  if (Attributes != 0) {
+    if ((Attributes & (~(PrivateData->Supports))) != 0) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  //
+  // This is a generic driver for a PC-AT class system.  It does not have any
+  // chipset specific knowlegde, so none of the attributes can be set or
+  // cleared.  Any attempt to set attribute that are already set will succeed,
+  // and any attempt to set an attribute that is not supported will fail.
+  //
+  if (Attributes & (~PrivateData->Attributes)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves the current resource settings of this PCI root bridge in the form
+  of a set of ACPI 2.0 resource descriptors.
+
+  There are only two resource descriptor types from the ACPI Specification that
+  may be used to describe the current resources allocated to a PCI root bridge.
+  These are the QWORD Address Space Descriptor (ACPI 2.0 Section 6.4.3.5.1),
+  and the End Tag (ACPI 2.0 Section 6.4.2.8). The QWORD Address Space
+  Descriptor can describe memory, I/O, and bus number ranges for dynamic or
+  fixed resources. The configuration of a PCI root bridge is described with one
+  or more QWORD Address Space Descriptors followed by an End Tag.
+
+  @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that
+                           describe the current configuration of this PCI root
+                           bridge. The storage for the ACPI 2.0 resource
+                           descriptors is allocated by this function. The
+                           caller must treat the return buffer as read-only
+                           data, and the buffer must not be freed by the
+                           caller.
+
+  @retval  EFI_SUCCESS     The current configuration of this PCI root bridge
+                           was returned in Resources.
+  @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge
+                           could not be retrieved.
+  @retval  EFI_INVALID_PARAMETER Invalid pointer of
+                                 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
+  OUT VOID                             **Resources
+  )
+{
+  PCI_ROOT_BRIDGE_INSTANCE  *PrivateData;
+  UINTN                     Index;
+
+  PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+  for (Index = 0; Index < TypeMax; Index++) {
+    if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
+      EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *Desc;
+
+      Desc               = &Configuration.SpaceDesp[Index];
+      Desc->AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
+      Desc->AddrRangeMax = PrivateData->ResAllocNode[Index].Base +
+                           PrivateData->ResAllocNode[Index].Length - 1;
+      Desc->AddrLen = PrivateData->ResAllocNode[Index].Length;
+    }
+  }
+
+  *Resources = &Configuration;
+  return EFI_SUCCESS;
+}
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114595): https://edk2.groups.io/g/devel/message/114595
Mute This Topic: https://groups.io/mt/103975472/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 19/32] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (17 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 18/32] AMD/VanGoghBoard: Check in PciHostBridge module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 20/32] AMD/VanGoghBoard: Check in FTPM module Zhai, MingXin (Duke) via groups.io
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table.
  It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid.

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>
---
 .../PcatRealTimeClockRuntimeDxe/PcRtc.c       | 1341 +++++++++++++++++
 .../PcatRealTimeClockRuntimeDxe/PcRtc.h       |  374 +++++
 .../PcatRealTimeClockRuntimeDxe/PcRtc.uni     |   17 +
 .../PcatRealTimeClockRuntimeDxe/PcRtcEntry.c  |  171 +++
 .../PcRtcExtra.uni                            |   15 +
 .../PcatRealTimeClockRuntimeDxe.inf           |   77 +
 6 files changed, 1995 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
new file mode 100644
index 0000000000..4e42d9d2ad
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
@@ -0,0 +1,1341 @@
+/** @file
+  RTC Architectural Protocol GUID as defined in DxeCis 0.96.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PcRtc.h"
+
+//
+// Days of month.
+//
+UINTN  mDayOfMonth[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+//
+// The name of NV variable to store the timezone and daylight saving information.
+//
+CHAR16  mTimeZoneVariableName[] = L"RTC";
+
+/**
+  Compare the Hour, Minute and Second of the From time and the To time.
+
+  Only compare H/M/S in EFI_TIME and ignore other fields here.
+
+  @param From   the first time
+  @param To     the second time
+
+  @return  >0   The H/M/S of the From time is later than those of To time
+  @return  ==0  The H/M/S of the From time is same as those of To time
+  @return  <0   The H/M/S of the From time is earlier than those of To time
+**/
+INTN
+CompareHMS (
+  IN EFI_TIME  *From,
+  IN EFI_TIME  *To
+  );
+
+/**
+  To check if second date is later than first date within 24 hours.
+
+  @param  From   the first date
+  @param  To     the second date
+
+  @retval TRUE   From is previous to To within 24 hours.
+  @retval FALSE  From is later, or it is previous to To more than 24 hours.
+**/
+BOOLEAN
+IsWithinOneDay (
+  IN EFI_TIME  *From,
+  IN EFI_TIME  *To
+  );
+
+/**
+  Read RTC content through its registers.
+
+  @param  Address  Address offset of RTC. It is recommended to use macros such as
+                   RTC_ADDRESS_SECONDS.
+
+  @return The data of UINT8 type read from RTC.
+**/
+UINT8
+RtcRead (
+  IN  UINT8  Address
+  )
+{
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
+  return IoRead8 (PCAT_RTC_DATA_REGISTER);
+}
+
+/**
+  Write RTC through its registers.
+
+  @param  Address  Address offset of RTC. It is recommended to use macros such as
+                   RTC_ADDRESS_SECONDS.
+  @param  Data     The content you want to write into RTC.
+
+**/
+VOID
+RtcWrite (
+  IN  UINT8  Address,
+  IN  UINT8  Data
+  )
+{
+  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8)(Address | (UINT8)(IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
+  IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);
+}
+
+/**
+  Initialize RTC.
+
+  @param  Global            For global use inside this module.
+
+  @retval EFI_DEVICE_ERROR  Initialization failed due to device error.
+  @retval EFI_SUCCESS       Initialization successful.
+
+**/
+EFI_STATUS
+PcRtcInit (
+  IN PC_RTC_MODULE_GLOBALS  *Global
+  )
+{
+  EFI_STATUS      Status;
+  RTC_REGISTER_B  RegisterB;
+  EFI_TIME        Time;
+  UINTN           DataSize;
+  UINT32          TimerVar;
+  BOOLEAN         Enabled;
+  BOOLEAN         Pending;
+
+  //
+  // Acquire RTC Lock to make access to RTC atomic
+  //
+  if (!EfiAtRuntime ()) {
+    EfiAcquireLock (&Global->RtcLock);
+  }
+
+  //
+  // Wait for up to 0.1 seconds for the RTC to be updated
+  //
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+  if (EFI_ERROR (Status)) {
+    //
+    // Set the variable with default value if the RTC is functioning incorrectly.
+    //
+    Global->SavedTimeZone = EFI_UNSPECIFIED_TIMEZONE;
+    Global->Daylight      = 0;
+    if (!EfiAtRuntime ()) {
+      EfiReleaseLock (&Global->RtcLock);
+    }
+
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Get the Time/Date/Daylight Savings values.
+  //
+  Time.Second = RtcRead (RTC_ADDRESS_SECONDS);
+  Time.Minute = RtcRead (RTC_ADDRESS_MINUTES);
+  Time.Hour   = RtcRead (RTC_ADDRESS_HOURS);
+  Time.Day    = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+  Time.Month  = RtcRead (RTC_ADDRESS_MONTH);
+  Time.Year   = RtcRead (RTC_ADDRESS_YEAR);
+
+  //
+  // Set RTC configuration after get original time
+  // The value of bit AIE should be reserved.
+  //
+  RegisterB.Data = FixedPcdGet8 (PcdInitialValueRtcRegisterB) | (RegisterB.Data & BIT5);
+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+  //
+  // Release RTC Lock.
+  //
+  if (!EfiAtRuntime ()) {
+    EfiReleaseLock (&Global->RtcLock);
+  }
+
+  //
+  // Get the data of Daylight saving and time zone, if they have been
+  // stored in NV variable during previous boot.
+  //
+  DataSize = sizeof (UINT32);
+  Status   = EfiGetVariable (
+               mTimeZoneVariableName,
+               &gEfiCallerIdGuid,
+               NULL,
+               &DataSize,
+               &TimerVar
+               );
+  if (!EFI_ERROR (Status)) {
+    Time.TimeZone = (INT16)TimerVar;
+    Time.Daylight = (UINT8)(TimerVar >> 16);
+  } else {
+    Time.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+    Time.Daylight = 0;
+  }
+
+  //
+  // Validate time fields
+  //
+  Status = ConvertRtcTimeToEfiTime (&Time, RegisterB);
+  if (!EFI_ERROR (Status)) {
+    Status = RtcTimeFieldsValid (&Time);
+  }
+
+  if (EFI_ERROR (Status)) {
+    //
+    // Report Status Code to indicate that the RTC has bad date and time
+    //
+    REPORT_STATUS_CODE (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      (EFI_SOFTWARE_DXE_RT_DRIVER | EFI_SW_EC_BAD_DATE_TIME)
+      );
+    Time.Second     = RTC_INIT_SECOND;
+    Time.Minute     = RTC_INIT_MINUTE;
+    Time.Hour       = RTC_INIT_HOUR;
+    Time.Day        = RTC_INIT_DAY;
+    Time.Month      = RTC_INIT_MONTH;
+    Time.Year       = PcdGet16 (PcdMinimalValidYear);
+    Time.Nanosecond = 0;
+    Time.TimeZone   = EFI_UNSPECIFIED_TIMEZONE;
+    Time.Daylight   = 0;
+  }
+
+  //
+  // Reset time value according to new RTC configuration
+  //
+  Status = PcRtcSetTime (&Time, Global);
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Reset wakeup time value to valid state when wakeup alarm is disabled and wakeup time is invalid.
+  // Global variable has already had valid SavedTimeZone and Daylight,
+  // so we can use them to get and set wakeup time.
+  //
+  Status = PcRtcGetWakeupTime (&Enabled, &Pending, &Time, Global);
+  if ((Enabled) || (!EFI_ERROR (Status))) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // When wakeup time is disabled and invalid, reset wakeup time register to valid state
+  // but keep wakeup alarm disabled.
+  //
+  Time.Second     = RTC_INIT_SECOND;
+  Time.Minute     = RTC_INIT_MINUTE;
+  Time.Hour       = RTC_INIT_HOUR;
+  Time.Day        = RTC_INIT_DAY;
+  Time.Month      = RTC_INIT_MONTH;
+  Time.Year       = PcdGet16 (PcdMinimalValidYear);
+  Time.Nanosecond = 0;
+  Time.TimeZone   = Global->SavedTimeZone;
+  Time.Daylight   = Global->Daylight;
+
+  //
+  // Acquire RTC Lock to make access to RTC atomic
+  //
+  if (!EfiAtRuntime ()) {
+    EfiAcquireLock (&Global->RtcLock);
+  }
+
+  //
+  // Wait for up to 0.1 seconds for the RTC to be updated
+  //
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+  if (EFI_ERROR (Status)) {
+    if (!EfiAtRuntime ()) {
+      EfiReleaseLock (&Global->RtcLock);
+    }
+
+    return EFI_DEVICE_ERROR;
+  }
+
+  ConvertEfiTimeToRtcTime (&Time, RegisterB);
+
+  //
+  // Set the Y/M/D info to variable as it has no corresponding hw registers.
+  //
+  Status =  EfiSetVariable (
+              L"RTCALARM",
+              &gEfiCallerIdGuid,
+              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+              sizeof (Time),
+              &Time
+              );
+  if (EFI_ERROR (Status)) {
+    if (!EfiAtRuntime ()) {
+      EfiReleaseLock (&Global->RtcLock);
+    }
+
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Inhibit updates of the RTC
+  //
+  RegisterB.Bits.Set = 1;
+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+  //
+  // Set RTC alarm time registers
+  //
+  RtcWrite (RTC_ADDRESS_SECONDS_ALARM, Time.Second);
+  RtcWrite (RTC_ADDRESS_MINUTES_ALARM, Time.Minute);
+  RtcWrite (RTC_ADDRESS_HOURS_ALARM, Time.Hour);
+
+  //
+  // Allow updates of the RTC registers
+  //
+  RegisterB.Bits.Set = 0;
+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+  //
+  // Release RTC Lock.
+  //
+  if (!EfiAtRuntime ()) {
+    EfiReleaseLock (&Global->RtcLock);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Returns the current time and date information, and the time-keeping capabilities
+  of the hardware platform.
+
+  @param  Time          A pointer to storage to receive a snapshot of the current time.
+  @param  Capabilities  An optional pointer to a buffer to receive the real time clock
+                        device's capabilities.
+  @param  Global        For global use inside this module.
+
+  @retval EFI_SUCCESS            The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER  Time is NULL.
+  @retval EFI_DEVICE_ERROR       The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+PcRtcGetTime (
+  OUT  EFI_TIME *Time,
+  OUT  EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL
+  IN   PC_RTC_MODULE_GLOBALS  *Global
+  )
+{
+  EFI_STATUS      Status;
+  RTC_REGISTER_B  RegisterB;
+
+  //
+  // Check parameters for null pointer
+  //
+  if (Time == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Acquire RTC Lock to make access to RTC atomic
+  //
+  if (!EfiAtRuntime ()) {
+    EfiAcquireLock (&Global->RtcLock);
+  }
+
+  //
+  // Wait for up to 0.1 seconds for the RTC to be updated
+  //
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+  if (EFI_ERROR (Status)) {
+    if (!EfiAtRuntime ()) {
+      EfiReleaseLock (&Global->RtcLock);
+    }
+
+    return Status;
+  }
+
+  //
+  // Read Register B
+  //
+  RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+  //
+  // Get the Time/Date/Daylight Savings values.
+  //
+  Time->Second = RtcRead (RTC_ADDRESS_SECONDS);
+  Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);
+  Time->Hour   = RtcRead (RTC_ADDRESS_HOURS);
+  Time->Day    = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+  Time->Month  = RtcRead (RTC_ADDRESS_MONTH);
+  Time->Year   = RtcRead (RTC_ADDRESS_YEAR);
+
+  //
+  // Release RTC Lock.
+  //
+  if (!EfiAtRuntime ()) {
+    EfiReleaseLock (&Global->RtcLock);
+  }
+
+  //
+  // Get the variable that contains the TimeZone and Daylight fields
+  //
+  Time->TimeZone = Global->SavedTimeZone;
+  Time->Daylight = Global->Daylight;
+
+  //
+  // Make sure all field values are in correct range
+  //
+  Status = ConvertRtcTimeToEfiTime (Time, RegisterB);
+  if (!EFI_ERROR (Status)) {
+    Status = RtcTimeFieldsValid (Time);
+  }
+
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  //  Fill in Capabilities if it was passed in
+  //
+  if (Capabilities != NULL) {
+    Capabilities->Resolution = 1;
+    //
+    // 1 hertz
+    //
+    Capabilities->Accuracy = 50000000;
+    //
+    // 50 ppm
+    //
+    Capabilities->SetsToZero = FALSE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Sets the current local time and date information.
+
+  @param  Time                  A pointer to the current time.
+  @param  Global                For global use inside this module.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER A time field is out of range.
+  @retval EFI_DEVICE_ERROR      The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+PcRtcSetTime (
+  IN EFI_TIME               *Time,
+  IN PC_RTC_MODULE_GLOBALS  *Global
+  )
+{
+  EFI_STATUS      Status;
+  EFI_TIME        RtcTime;
+  RTC_REGISTER_B  RegisterB;
+  UINT32          TimerVar;
+
+  if (Time == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Make sure that the time fields are valid
+  //
+  Status = RtcTimeFieldsValid (Time);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CopyMem (&RtcTime, Time, sizeof (EFI_TIME));
+
+  //
+  // Acquire RTC Lock to make access to RTC atomic
+  //
+  if (!EfiAtRuntime ()) {
+    EfiAcquireLock (&Global->RtcLock);
+  }
+
+  //
+  // Wait for up to 0.1 seconds for the RTC to be updated
+  //
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+  if (EFI_ERROR (Status)) {
+    if (!EfiAtRuntime ()) {
+      EfiReleaseLock (&Global->RtcLock);
+    }
+
+    return Status;
+  }
+
+  //
+  // Write timezone and daylight to RTC variable
+  //
+  if ((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) && (Time->Daylight == 0)) {
+    Status = EfiSetVariable (
+               mTimeZoneVariableName,
+               &gEfiCallerIdGuid,
+               0,
+               0,
+               NULL
+               );
+    if (Status == EFI_NOT_FOUND) {
+      Status = EFI_SUCCESS;
+    }
+  } else {
+    TimerVar = Time->Daylight;
+    TimerVar = (UINT32)((TimerVar << 16) | (UINT16)(Time->TimeZone));
+    Status   = EfiSetVariable (
+                 mTimeZoneVariableName,
+                 &gEfiCallerIdGuid,
+                 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                 sizeof (TimerVar),
+                 &TimerVar
+                 );
+  }
+
+  if (EFI_ERROR (Status)) {
+    if (!EfiAtRuntime ()) {
+      EfiReleaseLock (&Global->RtcLock);
+    }
+
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Read Register B, and inhibit updates of the RTC
+  //
+  RegisterB.Data     = RtcRead (RTC_ADDRESS_REGISTER_B);
+  RegisterB.Bits.Set = 1;
+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+  //
+  // Store the century value to RTC before converting to BCD format.
+  //
+  if (Global->CenturyRtcAddress != 0) {
+    RtcWrite (Global->CenturyRtcAddress, DecimalToBcd8 ((UINT8)(RtcTime.Year / 100)));
+  }
+
+  ConvertEfiTimeToRtcTime (&RtcTime, RegisterB);
+
+  RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);
+  RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);
+  RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour);
+  RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);
+  RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);
+  RtcWrite (RTC_ADDRESS_YEAR, (UINT8)RtcTime.Year);
+
+  //
+  // Allow updates of the RTC registers
+  //
+  RegisterB.Bits.Set = 0;
+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+  //
+  // Release RTC Lock.
+  //
+  if (!EfiAtRuntime ()) {
+    EfiReleaseLock (&Global->RtcLock);
+  }
+
+  //
+  // Set the variable that contains the TimeZone and Daylight fields
+  //
+  Global->SavedTimeZone = Time->TimeZone;
+  Global->Daylight      = Time->Daylight;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Returns the current wakeup alarm clock setting.
+
+  @param  Enabled  Indicates if the alarm is currently enabled or disabled.
+  @param  Pending  Indicates if the alarm signal is pending and requires acknowledgment.
+  @param  Time     The current alarm setting.
+  @param  Global   For global use inside this module.
+
+  @retval EFI_SUCCESS           The alarm settings were returned.
+  @retval EFI_INVALID_PARAMETER Enabled is NULL.
+  @retval EFI_INVALID_PARAMETER Pending is NULL.
+  @retval EFI_INVALID_PARAMETER Time is NULL.
+  @retval EFI_DEVICE_ERROR      The wakeup time could not be retrieved due to a hardware error.
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+PcRtcGetWakeupTime (
+  OUT BOOLEAN                *Enabled,
+  OUT BOOLEAN                *Pending,
+  OUT EFI_TIME               *Time,
+  IN  PC_RTC_MODULE_GLOBALS  *Global
+  )
+{
+  EFI_STATUS      Status;
+  RTC_REGISTER_B  RegisterB;
+  RTC_REGISTER_C  RegisterC;
+  EFI_TIME        RtcTime;
+  UINTN           DataSize;
+
+  //
+  // Check parameters for null pointers
+  //
+  if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Acquire RTC Lock to make access to RTC atomic
+  //
+  if (!EfiAtRuntime ()) {
+    EfiAcquireLock (&Global->RtcLock);
+  }
+
+  //
+  // Wait for up to 0.1 seconds for the RTC to be updated
+  //
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+  if (EFI_ERROR (Status)) {
+    if (!EfiAtRuntime ()) {
+      EfiReleaseLock (&Global->RtcLock);
+    }
+
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Read Register B and Register C
+  //
+  RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+  RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);
+
+  //
+  // Get the Time/Date/Daylight Savings values.
+  //
+  *Enabled = RegisterB.Bits.Aie;
+  *Pending = RegisterC.Bits.Af;
+
+  Time->Second   = RtcRead (RTC_ADDRESS_SECONDS_ALARM);
+  Time->Minute   = RtcRead (RTC_ADDRESS_MINUTES_ALARM);
+  Time->Hour     = RtcRead (RTC_ADDRESS_HOURS_ALARM);
+  Time->Day      = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+  Time->Month    = RtcRead (RTC_ADDRESS_MONTH);
+  Time->Year     = RtcRead (RTC_ADDRESS_YEAR);
+  Time->TimeZone = Global->SavedTimeZone;
+  Time->Daylight = Global->Daylight;
+
+  //
+  // Get the alarm info from variable
+  //
+  DataSize = sizeof (EFI_TIME);
+  Status   = EfiGetVariable (
+               L"RTCALARM",
+               &gEfiCallerIdGuid,
+               NULL,
+               &DataSize,
+               &RtcTime
+               );
+  if (!EFI_ERROR (Status)) {
+    //
+    // The alarm variable exists. In this case, we read variable to get info.
+    //
+    Time->Day   = RtcTime.Day;
+    Time->Month = RtcTime.Month;
+    Time->Year  = RtcTime.Year;
+  }
+
+  //
+  // Release RTC Lock.
+  //
+  if (!EfiAtRuntime ()) {
+    EfiReleaseLock (&Global->RtcLock);
+  }
+
+  //
+  // Make sure all field values are in correct range
+  //
+  Status = ConvertRtcTimeToEfiTime (Time, RegisterB);
+  if (!EFI_ERROR (Status)) {
+    Status = RtcTimeFieldsValid (Time);
+  }
+
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Sets the system wakeup alarm clock time.
+
+  @param  Enabled  Enable or disable the wakeup alarm.
+  @param  Time     If Enable is TRUE, the time to set the wakeup alarm for.
+                   If Enable is FALSE, then this parameter is optional, and may be NULL.
+  @param  Global   For global use inside this module.
+
+  @retval EFI_SUCCESS           If Enable is TRUE, then the wakeup alarm was enabled.
+                                If Enable is FALSE, then the wakeup alarm was disabled.
+  @retval EFI_INVALID_PARAMETER A time field is out of range.
+  @retval EFI_DEVICE_ERROR      The wakeup time could not be set due to a hardware error.
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+PcRtcSetWakeupTime (
+  IN BOOLEAN Enable,
+  IN EFI_TIME *Time, OPTIONAL
+  IN PC_RTC_MODULE_GLOBALS  *Global
+  )
+{
+  EFI_STATUS             Status;
+  EFI_TIME               RtcTime;
+  RTC_REGISTER_B         RegisterB;
+  EFI_TIME_CAPABILITIES  Capabilities;
+
+  ZeroMem (&RtcTime, sizeof (RtcTime));
+
+  if (Enable) {
+    if (Time == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Make sure that the time fields are valid
+    //
+    Status = RtcTimeFieldsValid (Time);
+    if (EFI_ERROR (Status)) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Just support set alarm time within 24 hours
+    //
+    PcRtcGetTime (&RtcTime, &Capabilities, Global);
+    Status = RtcTimeFieldsValid (&RtcTime);
+    if (EFI_ERROR (Status)) {
+      return EFI_DEVICE_ERROR;
+    }
+
+    if (!IsWithinOneDay (&RtcTime, Time)) {
+      return EFI_UNSUPPORTED;
+    }
+
+    //
+    // Make a local copy of the time and date
+    //
+    CopyMem (&RtcTime, Time, sizeof (EFI_TIME));
+  }
+
+  //
+  // Acquire RTC Lock to make access to RTC atomic
+  //
+  if (!EfiAtRuntime ()) {
+    EfiAcquireLock (&Global->RtcLock);
+  }
+
+  //
+  // Wait for up to 0.1 seconds for the RTC to be updated
+  //
+  Status = RtcWaitToUpdate (PcdGet32 (PcdRealTimeClockUpdateTimeout));
+  if (EFI_ERROR (Status)) {
+    if (!EfiAtRuntime ()) {
+      EfiReleaseLock (&Global->RtcLock);
+    }
+
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Read Register B
+  //
+  RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
+
+  if (Enable) {
+    ConvertEfiTimeToRtcTime (&RtcTime, RegisterB);
+  } else {
+    //
+    // if the alarm is disable, record the current setting.
+    //
+    RtcTime.Second   = RtcRead (RTC_ADDRESS_SECONDS_ALARM);
+    RtcTime.Minute   = RtcRead (RTC_ADDRESS_MINUTES_ALARM);
+    RtcTime.Hour     = RtcRead (RTC_ADDRESS_HOURS_ALARM);
+    RtcTime.Day      = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
+    RtcTime.Month    = RtcRead (RTC_ADDRESS_MONTH);
+    RtcTime.Year     = RtcRead (RTC_ADDRESS_YEAR);
+    RtcTime.TimeZone = Global->SavedTimeZone;
+    RtcTime.Daylight = Global->Daylight;
+  }
+
+  //
+  // Set the Y/M/D info to variable as it has no corresponding hw registers.
+  //
+  Status =  EfiSetVariable (
+              L"RTCALARM",
+              &gEfiCallerIdGuid,
+              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+              sizeof (RtcTime),
+              &RtcTime
+              );
+  if (EFI_ERROR (Status)) {
+    if (!EfiAtRuntime ()) {
+      EfiReleaseLock (&Global->RtcLock);
+    }
+
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Inhibit updates of the RTC
+  //
+  RegisterB.Bits.Set = 1;
+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+  if (Enable) {
+    //
+    // Set RTC alarm time
+    //
+    RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);
+    RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);
+    RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);
+
+    RegisterB.Bits.Aie = 1;
+  } else {
+    RegisterB.Bits.Aie = 0;
+  }
+
+  //
+  // Allow updates of the RTC registers
+  //
+  RegisterB.Bits.Set = 0;
+  RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
+
+  //
+  // Release RTC Lock.
+  //
+  if (!EfiAtRuntime ()) {
+    EfiReleaseLock (&Global->RtcLock);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Checks an 8-bit BCD value, and converts to an 8-bit value if valid.
+
+  This function checks the 8-bit BCD value specified by Value.
+  If valid, the function converts it to an 8-bit value and returns it.
+  Otherwise, return 0xff.
+
+  @param   Value The 8-bit BCD value to check and convert
+
+  @return  The 8-bit value converted. Or 0xff if Value is invalid.
+
+**/
+UINT8
+CheckAndConvertBcd8ToDecimal8 (
+  IN  UINT8  Value
+  )
+{
+  if ((Value < 0xa0) && ((Value & 0xf) < 0xa)) {
+    return BcdToDecimal8 (Value);
+  }
+
+  return 0xff;
+}
+
+/**
+  Converts time read from RTC to EFI_TIME format defined by UEFI spec.
+
+  This function converts raw time data read from RTC to the EFI_TIME format
+  defined by UEFI spec.
+  If data mode of RTC is BCD, then converts it to decimal,
+  If RTC is in 12-hour format, then converts it to 24-hour format.
+
+  @param   Time       On input, the time data read from RTC to convert
+                      On output, the time converted to UEFI format
+  @param   RegisterB  Value of Register B of RTC, indicating data mode
+                      and hour format.
+
+  @retval  EFI_INVALID_PARAMETER  Parameters passed in are invalid.
+  @retval  EFI_SUCCESS            Convert RTC time to EFI time successfully.
+
+**/
+EFI_STATUS
+ConvertRtcTimeToEfiTime (
+  IN OUT EFI_TIME        *Time,
+  IN     RTC_REGISTER_B  RegisterB
+  )
+{
+  BOOLEAN  IsPM;
+  UINT8    Century;
+
+  if ((Time->Hour & 0x80) != 0) {
+    IsPM = TRUE;
+  } else {
+    IsPM = FALSE;
+  }
+
+  Time->Hour = (UINT8)(Time->Hour & 0x7f);
+
+  if (RegisterB.Bits.Dm == 0) {
+    Time->Year   = CheckAndConvertBcd8ToDecimal8 ((UINT8)Time->Year);
+    Time->Month  = CheckAndConvertBcd8ToDecimal8 (Time->Month);
+    Time->Day    = CheckAndConvertBcd8ToDecimal8 (Time->Day);
+    Time->Hour   = CheckAndConvertBcd8ToDecimal8 (Time->Hour);
+    Time->Minute = CheckAndConvertBcd8ToDecimal8 (Time->Minute);
+    Time->Second = CheckAndConvertBcd8ToDecimal8 (Time->Second);
+  }
+
+  if ((Time->Year == 0xff) || (Time->Month == 0xff) || (Time->Day == 0xff) ||
+      (Time->Hour == 0xff) || (Time->Minute == 0xff) || (Time->Second == 0xff))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // For minimal/maximum year range [1970, 2069],
+  //   Century is 19 if RTC year >= 70,
+  //   Century is 20 otherwise.
+  //
+  Century = (UINT8)(PcdGet16 (PcdMinimalValidYear) / 100);
+  if (Time->Year < PcdGet16 (PcdMinimalValidYear) % 100) {
+    Century++;
+  }
+
+  Time->Year = (UINT16)(Century * 100 + Time->Year);
+
+  //
+  // If time is in 12 hour format, convert it to 24 hour format
+  //
+  if (RegisterB.Bits.Mil == 0) {
+    if (IsPM && (Time->Hour < 12)) {
+      Time->Hour = (UINT8)(Time->Hour + 12);
+    }
+
+    if (!IsPM && (Time->Hour == 12)) {
+      Time->Hour = 0;
+    }
+  }
+
+  Time->Nanosecond = 0;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Wait for a period for the RTC to be ready.
+
+  @param    Timeout  Tell how long it should take to wait.
+
+  @retval   EFI_DEVICE_ERROR   RTC device error.
+  @retval   EFI_SUCCESS        RTC is updated and ready.
+**/
+EFI_STATUS
+RtcWaitToUpdate (
+  UINTN  Timeout
+  )
+{
+  RTC_REGISTER_A  RegisterA;
+  RTC_REGISTER_D  RegisterD;
+
+  //
+  // See if the RTC is functioning correctly
+  //
+  RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
+
+  if (RegisterD.Bits.Vrt == 0) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Wait for up to 0.1 seconds for the RTC to be ready.
+  //
+  Timeout        = (Timeout / 10) + 1;
+  RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
+  while (RegisterA.Bits.Uip == 1 && Timeout > 0) {
+    MicroSecondDelay (10);
+    RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
+    Timeout--;
+  }
+
+  RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
+  if ((Timeout == 0) || (RegisterD.Bits.Vrt == 0)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  See if all fields of a variable of EFI_TIME type is correct.
+
+  @param   Time   The time to be checked.
+
+  @retval  EFI_INVALID_PARAMETER  Some fields of Time are not correct.
+  @retval  EFI_SUCCESS            Time is a valid EFI_TIME variable.
+
+**/
+EFI_STATUS
+RtcTimeFieldsValid (
+  IN EFI_TIME  *Time
+  )
+{
+  if ((Time->Year < PcdGet16 (PcdMinimalValidYear)) ||
+      (Time->Year > PcdGet16 (PcdMaximalValidYear)) ||
+      (Time->Month < 1) ||
+      (Time->Month > 12) ||
+      (!DayValid (Time)) ||
+      (Time->Hour > 23) ||
+      (Time->Minute > 59) ||
+      (Time->Second > 59) ||
+      (Time->Nanosecond > 999999999) ||
+      (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) ||
+      ((Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) != 0))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  See if field Day of an EFI_TIME is correct.
+
+  @param    Time   Its Day field is to be checked.
+
+  @retval   TRUE   Day field of Time is correct.
+  @retval   FALSE  Day field of Time is NOT correct.
+**/
+BOOLEAN
+DayValid (
+  IN  EFI_TIME  *Time
+  )
+{
+  //
+  // The validity of Time->Month field should be checked before
+  //
+  ASSERT (Time->Month >= 1);
+  ASSERT (Time->Month <= 12);
+  if ((Time->Day < 1) ||
+      (Time->Day > mDayOfMonth[Time->Month - 1]) ||
+      ((Time->Month == 2) && (!IsLeapYear (Time) && (Time->Day > 28)))
+      )
+  {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Check if it is a leap year.
+
+  @param    Time   The time to be checked.
+
+  @retval   TRUE   It is a leap year.
+  @retval   FALSE  It is NOT a leap year.
+**/
+BOOLEAN
+IsLeapYear (
+  IN EFI_TIME  *Time
+  )
+{
+  if (Time->Year % 4 == 0) {
+    if (Time->Year % 100 == 0) {
+      if (Time->Year % 400 == 0) {
+        return TRUE;
+      } else {
+        return FALSE;
+      }
+    } else {
+      return TRUE;
+    }
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Converts time from EFI_TIME format defined by UEFI spec to RTC's.
+
+  This function converts time from EFI_TIME format defined by UEFI spec to RTC's.
+  If data mode of RTC is BCD, then converts EFI_TIME to it.
+  If RTC is in 12-hour format, then converts EFI_TIME to it.
+
+  @param   Time       On input, the time data read from UEFI to convert
+                      On output, the time converted to RTC format
+  @param   RegisterB  Value of Register B of RTC, indicating data mode
+**/
+VOID
+ConvertEfiTimeToRtcTime (
+  IN OUT EFI_TIME        *Time,
+  IN     RTC_REGISTER_B  RegisterB
+  )
+{
+  BOOLEAN  IsPM;
+
+  IsPM = TRUE;
+  //
+  // Adjust hour field if RTC is in 12 hour mode
+  //
+  if (RegisterB.Bits.Mil == 0) {
+    if (Time->Hour < 12) {
+      IsPM = FALSE;
+    }
+
+    if (Time->Hour >= 13) {
+      Time->Hour = (UINT8)(Time->Hour - 12);
+    } else if (Time->Hour == 0) {
+      Time->Hour = 12;
+    }
+  }
+
+  //
+  // Set the Time/Date values.
+  //
+  Time->Year = (UINT16)(Time->Year % 100);
+
+  if (RegisterB.Bits.Dm == 0) {
+    Time->Year   = DecimalToBcd8 ((UINT8)Time->Year);
+    Time->Month  = DecimalToBcd8 (Time->Month);
+    Time->Day    = DecimalToBcd8 (Time->Day);
+    Time->Hour   = DecimalToBcd8 (Time->Hour);
+    Time->Minute = DecimalToBcd8 (Time->Minute);
+    Time->Second = DecimalToBcd8 (Time->Second);
+  }
+
+  //
+  // If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.
+  //
+  if ((RegisterB.Bits.Mil == 0) && IsPM) {
+    Time->Hour = (UINT8)(Time->Hour | 0x80);
+  }
+}
+
+/**
+  Compare the Hour, Minute and Second of the From time and the To time.
+
+  Only compare H/M/S in EFI_TIME and ignore other fields here.
+
+  @param From   the first time
+  @param To     the second time
+
+  @return  >0   The H/M/S of the From time is later than those of To time
+  @return  ==0  The H/M/S of the From time is same as those of To time
+  @return  <0   The H/M/S of the From time is earlier than those of To time
+**/
+INTN
+CompareHMS (
+  IN EFI_TIME  *From,
+  IN EFI_TIME  *To
+  )
+{
+  if ((From->Hour > To->Hour) ||
+      ((From->Hour == To->Hour) && (From->Minute > To->Minute)) ||
+      ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second > To->Second)))
+  {
+    return 1;
+  } else if ((From->Hour == To->Hour) && (From->Minute == To->Minute) && (From->Second == To->Second)) {
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+/**
+  To check if second date is later than first date within 24 hours.
+
+  @param  From   the first date
+  @param  To     the second date
+
+  @retval TRUE   From is previous to To within 24 hours.
+  @retval FALSE  From is later, or it is previous to To more than 24 hours.
+**/
+BOOLEAN
+IsWithinOneDay (
+  IN EFI_TIME  *From,
+  IN EFI_TIME  *To
+  )
+{
+  BOOLEAN  Adjacent;
+
+  Adjacent = FALSE;
+
+  //
+  // The validity of From->Month field should be checked before
+  //
+  ASSERT (From->Month >= 1);
+  ASSERT (From->Month <= 12);
+
+  if (From->Year == To->Year) {
+    if (From->Month == To->Month) {
+      if ((From->Day + 1) == To->Day) {
+        if ((CompareHMS (From, To) >= 0)) {
+          Adjacent = TRUE;
+        }
+      } else if (From->Day == To->Day) {
+        if ((CompareHMS (From, To) <= 0)) {
+          Adjacent = TRUE;
+        }
+      }
+    } else if (((From->Month + 1) == To->Month) && (To->Day == 1)) {
+      if ((From->Month == 2) && !IsLeapYear (From)) {
+        if (From->Day == 28) {
+          if ((CompareHMS (From, To) >= 0)) {
+            Adjacent = TRUE;
+          }
+        }
+      } else if (From->Day == mDayOfMonth[From->Month - 1]) {
+        if ((CompareHMS (From, To) >= 0)) {
+          Adjacent = TRUE;
+        }
+      }
+    }
+  } else if (((From->Year + 1) == To->Year) &&
+             (From->Month == 12) &&
+             (From->Day   == 31) &&
+             (To->Month   == 1)  &&
+             (To->Day     == 1))
+  {
+    if ((CompareHMS (From, To) >= 0)) {
+      Adjacent = TRUE;
+    }
+  }
+
+  return Adjacent;
+}
+
+/**
+  This function find ACPI table with the specified signature in RSDT or XSDT.
+
+  @param Sdt              ACPI RSDT or XSDT.
+  @param Signature        ACPI table signature.
+  @param TablePointerSize Size of table pointer: 4 or 8.
+
+  @return ACPI table or NULL if not found.
+**/
+VOID *
+ScanTableInSDTRtc (
+  IN EFI_ACPI_DESCRIPTION_HEADER  *Sdt,
+  IN UINT32                       Signature,
+  IN UINTN                        TablePointerSize
+  )
+{
+  UINTN                        Index;
+  UINTN                        EntryCount;
+  UINTN                        EntryBase;
+  EFI_ACPI_DESCRIPTION_HEADER  *Table;
+
+  EntryCount = (Sdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / TablePointerSize;
+
+  EntryBase = (UINTN)(Sdt + 1);
+  for (Index = 0; Index < EntryCount; Index++) {
+    //
+    // When TablePointerSize is 4 while sizeof (VOID *) is 8, make sure the upper 4 bytes are zero.
+    //
+    Table = 0;
+    CopyMem (&Table, (VOID *)(EntryBase + Index * TablePointerSize), TablePointerSize);
+
+    if (Table == NULL) {
+      continue;
+    }
+
+    if (Table->Signature == Signature) {
+      return Table;
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Get the century RTC address from the ACPI FADT table.
+
+  @return  The century RTC address or 0 if not found.
+**/
+UINT8
+GetCenturyRtcAddress (
+  VOID
+  )
+{
+  EFI_STATUS                                    Status;
+  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;
+  EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt;
+
+  Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **)&Rsdp);
+  if (EFI_ERROR (Status)) {
+    Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&Rsdp);
+  }
+
+  if (EFI_ERROR (Status) || (Rsdp == NULL)) {
+    return 0;
+  }
+
+  Fadt = NULL;
+
+  //
+  // Find FADT in XSDT
+  //
+  if ((Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) && (Rsdp->XsdtAddress != 0)) {
+    Fadt = ScanTableInSDTRtc (
+             (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress,
+             EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+             sizeof (UINTN)
+             );
+  }
+
+  //
+  // Find FADT in RSDT
+  //
+  if ((Fadt == NULL) && (Rsdp->RsdtAddress != 0)) {
+    Fadt = ScanTableInSDTRtc (
+             (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress,
+             EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+             sizeof (UINT32)
+             );
+  }
+
+  if ((Fadt != NULL) &&
+      (Fadt->Century > RTC_ADDRESS_REGISTER_D) && (Fadt->Century < 0x80)
+      )
+  {
+    return Fadt->Century;
+  } else {
+    return 0;
+  }
+}
+
+/**
+  Notification function of ACPI Table change.
+
+  This is a notification function registered on ACPI Table change event.
+  It saves the Century address stored in ACPI FADT table.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+PcRtcAcpiTableChangeCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EFI_STATUS  Status;
+  EFI_TIME    Time;
+  UINT8       CenturyRtcAddress;
+  UINT8       Century;
+
+  CenturyRtcAddress = GetCenturyRtcAddress ();
+  if ((CenturyRtcAddress != 0) && (mModuleGlobal.CenturyRtcAddress != CenturyRtcAddress)) {
+    mModuleGlobal.CenturyRtcAddress = CenturyRtcAddress;
+    Status                          = PcRtcGetTime (&Time, NULL, &mModuleGlobal);
+    if (!EFI_ERROR (Status)) {
+      Century = (UINT8)(Time.Year / 100);
+      Century = DecimalToBcd8 (Century);
+      DEBUG ((DEBUG_INFO, "PcRtc: Write 0x%x to CMOS location 0x%x\n", Century, mModuleGlobal.CenturyRtcAddress));
+      RtcWrite (mModuleGlobal.CenturyRtcAddress, Century);
+    }
+  }
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h
new file mode 100644
index 0000000000..62551de1d5
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h
@@ -0,0 +1,374 @@
+/** @file
+  Header file for real time clock driver.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RTC_H_
+#define RTC_H_
+
+#include <Uefi.h>
+
+#include <Guid/Acpi.h>
+
+#include <Protocol/RealTimeClock.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ReportStatusCodeLib.h>
+
+typedef struct {
+  EFI_LOCK    RtcLock;
+  INT16       SavedTimeZone;
+  UINT8       Daylight;
+  UINT8       CenturyRtcAddress;
+} PC_RTC_MODULE_GLOBALS;
+
+extern PC_RTC_MODULE_GLOBALS  mModuleGlobal;
+
+#define PCAT_RTC_ADDRESS_REGISTER  0x70
+#define PCAT_RTC_DATA_REGISTER     0x71
+
+//
+// Dallas DS12C887 Real Time Clock
+//
+#define RTC_ADDRESS_SECONDS           0   // R/W  Range 0..59
+#define RTC_ADDRESS_SECONDS_ALARM     1   // R/W  Range 0..59
+#define RTC_ADDRESS_MINUTES           2   // R/W  Range 0..59
+#define RTC_ADDRESS_MINUTES_ALARM     3   // R/W  Range 0..59
+#define RTC_ADDRESS_HOURS             4   // R/W  Range 1..12 or 0..23 Bit 7 is AM/PM
+#define RTC_ADDRESS_HOURS_ALARM       5   // R/W  Range 1..12 or 0..23 Bit 7 is AM/PM
+#define RTC_ADDRESS_DAY_OF_THE_WEEK   6   // R/W  Range 1..7
+#define RTC_ADDRESS_DAY_OF_THE_MONTH  7   // R/W  Range 1..31
+#define RTC_ADDRESS_MONTH             8   // R/W  Range 1..12
+#define RTC_ADDRESS_YEAR              9   // R/W  Range 0..99
+#define RTC_ADDRESS_REGISTER_A        10  // R/W[0..6]  R0[7]
+#define RTC_ADDRESS_REGISTER_B        11  // R/W
+#define RTC_ADDRESS_REGISTER_C        12  // RO
+#define RTC_ADDRESS_REGISTER_D        13  // RO
+//
+// Date and time initial values.
+// They are used if the RTC values are invalid during driver initialization
+//
+#define RTC_INIT_SECOND  0
+#define RTC_INIT_MINUTE  0
+#define RTC_INIT_HOUR    0
+#define RTC_INIT_DAY     1
+#define RTC_INIT_MONTH   1
+
+#pragma pack(1)
+//
+// Register A
+//
+typedef struct {
+  UINT8    Rs  : 4; // Rate Selection Bits
+  UINT8    Dv  : 3; // Divisor
+  UINT8    Uip : 1; // Update in progress
+} RTC_REGISTER_A_BITS;
+
+typedef union {
+  RTC_REGISTER_A_BITS    Bits;
+  UINT8                  Data;
+} RTC_REGISTER_A;
+
+//
+// Register B
+//
+typedef struct {
+  UINT8    Dse  : 1; // 0 - Daylight saving disabled  1 - Daylight savings enabled
+  UINT8    Mil  : 1; // 0 - 12 hour mode              1 - 24 hour mode
+  UINT8    Dm   : 1; // 0 - BCD Format                1 - Binary Format
+  UINT8    Sqwe : 1; // 0 - Disable SQWE output       1 - Enable SQWE output
+  UINT8    Uie  : 1; // 0 - Update INT disabled       1 - Update INT enabled
+  UINT8    Aie  : 1; // 0 - Alarm INT disabled        1 - Alarm INT Enabled
+  UINT8    Pie  : 1; // 0 - Periodic INT disabled     1 - Periodic INT Enabled
+  UINT8    Set  : 1; // 0 - Normal operation.         1 - Updates inhibited
+} RTC_REGISTER_B_BITS;
+
+typedef union {
+  RTC_REGISTER_B_BITS    Bits;
+  UINT8                  Data;
+} RTC_REGISTER_B;
+
+//
+// Register C
+//
+typedef struct {
+  UINT8    Reserved : 4; // Read as zero.  Can not be written.
+  UINT8    Uf       : 1; // Update End Interrupt Flag
+  UINT8    Af       : 1; // Alarm Interrupt Flag
+  UINT8    Pf       : 1; // Periodic Interrupt Flag
+  UINT8    Irqf     : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE
+} RTC_REGISTER_C_BITS;
+
+typedef union {
+  RTC_REGISTER_C_BITS    Bits;
+  UINT8                  Data;
+} RTC_REGISTER_C;
+
+//
+// Register D
+//
+typedef struct {
+  UINT8    Reserved : 7; // Read as zero.  Can not be written.
+  UINT8    Vrt      : 1; // Valid RAM and Time
+} RTC_REGISTER_D_BITS;
+
+typedef union {
+  RTC_REGISTER_D_BITS    Bits;
+  UINT8                  Data;
+} RTC_REGISTER_D;
+
+#pragma pack()
+
+/**
+  Initialize RTC.
+
+  @param  Global            For global use inside this module.
+
+  @retval EFI_DEVICE_ERROR  Initialization failed due to device error.
+  @retval EFI_SUCCESS       Initialization successful.
+
+**/
+EFI_STATUS
+PcRtcInit (
+  IN PC_RTC_MODULE_GLOBALS  *Global
+  );
+
+/**
+  Sets the current local time and date information.
+
+  @param  Time                  A pointer to the current time.
+  @param  Global                For global use inside this module.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER A time field is out of range.
+  @retval EFI_DEVICE_ERROR      The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+PcRtcSetTime (
+  IN EFI_TIME               *Time,
+  IN PC_RTC_MODULE_GLOBALS  *Global
+  );
+
+/**
+  Returns the current time and date information, and the time-keeping capabilities
+  of the hardware platform.
+
+  @param  Time          A pointer to storage to receive a snapshot of the current time.
+  @param  Capabilities  An optional pointer to a buffer to receive the real time clock
+                        device's capabilities.
+  @param  Global        For global use inside this module.
+
+  @retval EFI_SUCCESS            The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER  Time is NULL.
+  @retval EFI_DEVICE_ERROR       The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+PcRtcGetTime (
+  OUT EFI_TIME *Time,
+  OUT EFI_TIME_CAPABILITIES *Capabilities, OPTIONAL
+  IN  PC_RTC_MODULE_GLOBALS *Global
+  );
+
+/**
+  Sets the system wakeup alarm clock time.
+
+  @param  Enabled  Enable or disable the wakeup alarm.
+  @param  Time     If Enable is TRUE, the time to set the wakeup alarm for.
+                   If Enable is FALSE, then this parameter is optional, and may be NULL.
+  @param  Global   For global use inside this module.
+
+  @retval EFI_SUCCESS           If Enable is TRUE, then the wakeup alarm was enabled.
+                                If Enable is FALSE, then the wakeup alarm was disabled.
+  @retval EFI_INVALID_PARAMETER A time field is out of range.
+  @retval EFI_DEVICE_ERROR      The wakeup time could not be set due to a hardware error.
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+PcRtcSetWakeupTime (
+  IN BOOLEAN Enable,
+  IN EFI_TIME *Time, OPTIONAL
+  IN PC_RTC_MODULE_GLOBALS  *Global
+  );
+
+/**
+  Returns the current wakeup alarm clock setting.
+
+  @param  Enabled  Indicates if the alarm is currently enabled or disabled.
+  @param  Pending  Indicates if the alarm signal is pending and requires acknowledgement.
+  @param  Time     The current alarm setting.
+  @param  Global   For global use inside this module.
+
+  @retval EFI_SUCCESS           The alarm settings were returned.
+  @retval EFI_INVALID_PARAMETER Enabled is NULL.
+  @retval EFI_INVALID_PARAMETER Pending is NULL.
+  @retval EFI_INVALID_PARAMETER Time is NULL.
+  @retval EFI_DEVICE_ERROR      The wakeup time could not be retrieved due to a hardware error.
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+PcRtcGetWakeupTime (
+  OUT BOOLEAN                *Enabled,
+  OUT BOOLEAN                *Pending,
+  OUT EFI_TIME               *Time,
+  IN  PC_RTC_MODULE_GLOBALS  *Global
+  );
+
+/**
+  The user Entry Point for PcRTC module.
+
+  This is the entrhy point for PcRTC module. It installs the UEFI runtime service
+  including GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().
+
+  @param  ImageHandle    The firmware allocated handle for the EFI image.
+  @param  SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS    The entry point is executed successfully.
+  @retval Others         Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePcRtc (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+/**
+  See if all fields of a variable of EFI_TIME type is correct.
+
+  @param   Time   The time to be checked.
+
+  @retval  EFI_INVALID_PARAMETER  Some fields of Time are not correct.
+  @retval  EFI_SUCCESS            Time is a valid EFI_TIME variable.
+
+**/
+EFI_STATUS
+RtcTimeFieldsValid (
+  IN EFI_TIME  *Time
+  );
+
+/**
+  Converts time from EFI_TIME format defined by UEFI spec to RTC's.
+
+  This function converts time from EFI_TIME format defined by UEFI spec to RTC's.
+  If data mode of RTC is BCD, then converts EFI_TIME to it.
+  If RTC is in 12-hour format, then converts EFI_TIME to it.
+
+  @param   Time       On input, the time data read from UEFI to convert
+                      On output, the time converted to RTC format
+  @param   RegisterB  Value of Register B of RTC, indicating data mode
+**/
+VOID
+ConvertEfiTimeToRtcTime (
+  IN OUT EFI_TIME        *Time,
+  IN     RTC_REGISTER_B  RegisterB
+  );
+
+/**
+  Converts time read from RTC to EFI_TIME format defined by UEFI spec.
+
+  This function converts raw time data read from RTC to the EFI_TIME format
+  defined by UEFI spec.
+  If data mode of RTC is BCD, then converts it to decimal,
+  If RTC is in 12-hour format, then converts it to 24-hour format.
+
+  @param   Time       On input, the time data read from RTC to convert
+                      On output, the time converted to UEFI format
+  @param   RegisterB  Value of Register B of RTC, indicating data mode
+                      and hour format.
+
+  @retval  EFI_INVALID_PARAMETER  Parameters passed in are invalid.
+  @retval  EFI_SUCCESS            Convert RTC time to EFI time successfully.
+
+**/
+EFI_STATUS
+ConvertRtcTimeToEfiTime (
+  IN OUT EFI_TIME        *Time,
+  IN     RTC_REGISTER_B  RegisterB
+  );
+
+/**
+  Wait for a period for the RTC to be ready.
+
+  @param    Timeout  Tell how long it should take to wait.
+
+  @retval   EFI_DEVICE_ERROR   RTC device error.
+  @retval   EFI_SUCCESS        RTC is updated and ready.
+**/
+EFI_STATUS
+RtcWaitToUpdate (
+  UINTN  Timeout
+  );
+
+/**
+  See if field Day of an EFI_TIME is correct.
+
+  @param    Time   Its Day field is to be checked.
+
+  @retval   TRUE   Day field of Time is correct.
+  @retval   FALSE  Day field of Time is NOT correct.
+**/
+BOOLEAN
+DayValid (
+  IN  EFI_TIME  *Time
+  );
+
+/**
+  Check if it is a leapyear.
+
+  @param    Time   The time to be checked.
+
+  @retval   TRUE   It is a leapyear.
+  @retval   FALSE  It is NOT a leapyear.
+**/
+BOOLEAN
+IsLeapYear (
+  IN EFI_TIME  *Time
+  );
+
+/**
+  Get the century RTC address from the ACPI FADT table.
+
+  @return  The century RTC address or 0 if not found.
+**/
+UINT8
+GetCenturyRtcAddress (
+  VOID
+  );
+
+/**
+  Notification function of ACPI Table change.
+
+  This is a notification function registered on ACPI Table change event.
+  It saves the Century address stored in ACPI FADT table.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+PcRtcAcpiTableChangeCallback (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.uni b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.uni
new file mode 100644
index 0000000000..33d7211191
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.uni
@@ -0,0 +1,17 @@
+// /** @file
+// PcRtc driver to install EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL
+// This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table.
+// It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid.
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "PcRtc driver to install EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table. It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid."
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
new file mode 100644
index 0000000000..9ac9914fb2
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
@@ -0,0 +1,171 @@
+/** @file
+  Provides Set/Get time operations.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PcRtc.h"
+
+PC_RTC_MODULE_GLOBALS  mModuleGlobal;
+
+EFI_HANDLE  mHandle = NULL;
+
+/**
+  Returns the current time and date information, and the time-keeping capabilities
+  of the hardware platform.
+
+  @param  Time          A pointer to storage to receive a snapshot of the current time.
+  @param  Capabilities  An optional pointer to a buffer to receive the real time
+                        clock device's capabilities.
+
+  @retval EFI_SUCCESS            The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER  Time is NULL.
+  @retval EFI_DEVICE_ERROR       The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+PcRtcEfiGetTime (
+  OUT EFI_TIME               *Time,
+  OUT EFI_TIME_CAPABILITIES  *Capabilities  OPTIONAL
+  )
+{
+  return PcRtcGetTime (Time, Capabilities, &mModuleGlobal);
+}
+
+/**
+  Sets the current local time and date information.
+
+  @param  Time                   A pointer to the current time.
+
+  @retval EFI_SUCCESS            The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER  A time field is out of range.
+  @retval EFI_DEVICE_ERROR       The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+PcRtcEfiSetTime (
+  IN EFI_TIME  *Time
+  )
+{
+  return PcRtcSetTime (Time, &mModuleGlobal);
+}
+
+/**
+  Returns the current wakeup alarm clock setting.
+
+  @param  Enabled  Indicates if the alarm is currently enabled or disabled.
+  @param  Pending  Indicates if the alarm signal is pending and requires acknowledgement.
+  @param  Time     The current alarm setting.
+
+  @retval EFI_SUCCESS           The alarm settings were returned.
+  @retval EFI_INVALID_PARAMETER Enabled is NULL.
+  @retval EFI_INVALID_PARAMETER Pending is NULL.
+  @retval EFI_INVALID_PARAMETER Time is NULL.
+  @retval EFI_DEVICE_ERROR      The wakeup time could not be retrieved due to a hardware error.
+  @retval EFI_UNSUPPORTED       A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+PcRtcEfiGetWakeupTime (
+  OUT BOOLEAN   *Enabled,
+  OUT BOOLEAN   *Pending,
+  OUT EFI_TIME  *Time
+  )
+{
+  return PcRtcGetWakeupTime (Enabled, Pending, Time, &mModuleGlobal);
+}
+
+/**
+  Sets the system wakeup alarm clock time.
+
+  @param  Enabled  Enable or disable the wakeup alarm.
+  @param  Time     If Enable is TRUE, the time to set the wakeup alarm for.
+                   If Enable is FALSE, then this parameter is optional, and may be NULL.
+
+  @retval EFI_SUCCESS            If Enable is TRUE, then the wakeup alarm was enabled.
+                                 If Enable is FALSE, then the wakeup alarm was disabled.
+  @retval EFI_INVALID_PARAMETER  A time field is out of range.
+  @retval EFI_DEVICE_ERROR       The wakeup time could not be set due to a hardware error.
+  @retval EFI_UNSUPPORTED        A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+PcRtcEfiSetWakeupTime (
+  IN BOOLEAN   Enabled,
+  IN EFI_TIME  *Time       OPTIONAL
+  )
+{
+  return PcRtcSetWakeupTime (Enabled, Time, &mModuleGlobal);
+}
+
+/**
+  The user Entry Point for PcRTC module.
+
+  This is the entrhy point for PcRTC module. It installs the UEFI runtime service
+  including GetTime(),SetTime(),GetWakeupTime(),and SetWakeupTime().
+
+  @param  ImageHandle    The firmware allocated handle for the EFI image.
+  @param  SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS    The entry point is executed successfully.
+  @retval Others         Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePcRtc (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_EVENT   Event;
+
+  EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_CALLBACK);
+  mModuleGlobal.CenturyRtcAddress = GetCenturyRtcAddress ();
+
+  Status = PcRtcInit (&mModuleGlobal);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  PcRtcAcpiTableChangeCallback,
+                  NULL,
+                  &gEfiAcpi10TableGuid,
+                  &Event
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  PcRtcAcpiTableChangeCallback,
+                  NULL,
+                  &gEfiAcpiTableGuid,
+                  &Event
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  gRT->GetTime       = PcRtcEfiGetTime;
+  gRT->SetTime       = PcRtcEfiSetTime;
+  gRT->GetWakeupTime = PcRtcEfiGetWakeupTime;
+  gRT->SetWakeupTime = PcRtcEfiSetWakeupTime;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mHandle,
+                  &gEfiRealTimeClockArchProtocolGuid,
+                  NULL,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcExtra.uni
new file mode 100644
index 0000000000..59f4ed64d1
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcExtra.uni
@@ -0,0 +1,15 @@
+// /** @file
+// PcRtc Extra Localized Strings and Content
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"PCAT Real Time Clock DXE Driver"
+
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
new file mode 100644
index 0000000000..99818777c8
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
@@ -0,0 +1,77 @@
+## @file
+#  Pcat RealTimeClock Runtime Dxe
+# This driver provides GetTime, SetTime, GetWakeupTime, SetWakeupTime services to Runtime Service Table.
+# It will install a tagging protocol with gEfiRealTimeClockArchProtocolGuid.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PcRtc
+  MODULE_UNI_FILE                = PcRtc.uni
+  FILE_GUID                      = 378D7B65-8DA9-4773-B6E4-A47826A833E1
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializePcRtc
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  PcRtcEntry.c
+  PcRtc.c
+  PcRtc.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  PcAtChipsetPkg/PcAtChipsetPkg.dec
+
+[LibraryClasses]
+  UefiRuntimeServicesTableLib
+  UefiRuntimeLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  TimerLib
+  IoLib
+  BaseMemoryLib
+  UefiLib
+  DebugLib
+  BaseLib
+  PcdLib
+  ReportStatusCodeLib
+
+[Protocols]
+  gEfiRealTimeClockArchProtocolGuid             ## PRODUCES
+
+[Guids]
+  ## SOMETIMES_CONSUMES ## Event
+  ## SOMETIMES_CONSUMES ## SystemTable
+  gEfiAcpi10TableGuid
+
+  ## SOMETIMES_CONSUMES ## Event
+  ## SOMETIMES_CONSUMES ## SystemTable
+  gEfiAcpiTableGuid
+
+[FixedPcd]
+  gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterA     ## CONSUMES
+  gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterB     ## CONSUMES
+  gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterD     ## CONSUMES
+
+[Pcd]
+  gPcAtChipsetPkgTokenSpaceGuid.PcdRealTimeClockUpdateTimeout  ## CONSUMES
+  gPcAtChipsetPkgTokenSpaceGuid.PcdMinimalValidYear             ## CONSUMES
+  gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear             ## CONSUMES
+
+[Depex]
+  gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  PcRtcExtra.uni
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114594): https://edk2.groups.io/g/devel/message/114594
Mute This Topic: https://groups.io/mt/103975470/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 20/32] AMD/VanGoghBoard: Check in FTPM module
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (18 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 19/32] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 21/32] AMD/VanGoghBoard: Check in SignedCapsule Zhai, MingXin (Duke) via groups.io
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  This driver implements TPM 2.0 definition block in ACPI table and
  registers SMI callback functions for Tcg2 physical presence and
  MemoryClear to handle the requests from ACPI method.

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>
---
 .../DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c   |  113 ++
 .../DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf |   48 +
 .../PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c   |  141 ++
 .../PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf |   47 +
 .../AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c |  108 ++
 .../Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf       |   43 +
 .../Tpm2InstanceLibAmdFTpm.inf                |   53 +
 .../Tpm2InstanceLibAmdFTpmDxe.c               |  109 ++
 .../Tpm2InstanceLibAmdFTpmPei.c               |  153 ++
 .../DxeTcg2PhysicalPresenceLib.c              | 1269 +++++++++++++++++
 .../DxeTcg2PhysicalPresenceLib.inf            |   68 +
 .../DxeTcg2PhysicalPresenceLib.uni            |   22 +
 .../PhysicalPresenceStrings.uni               |   57 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c         |  854 +++++++++++
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h         |  123 ++
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf       |   92 ++
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni       |   19 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni  |   15 +
 .../Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl           |  397 ++++++
 .../Tcg/Tcg2Config/Tcg2ConfigNvData.h         |  124 ++
 .../Tcg/Tcg2Config/Tcg2ConfigPei.inf          |   77 +
 .../Tcg/Tcg2Config/Tcg2ConfigPei.uni          |   14 +
 .../Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni     |   15 +
 .../Tcg/Tcg2Config/Tcg2ConfigPeim.c           |  148 ++
 .../SecurityPkg/Tcg/Tcg2Config/TpmDetection.c |   99 ++
 25 files changed, 4208 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmPei.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
new file mode 100644
index 0000000000..fe359cdc28
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
@@ -0,0 +1,113 @@
+/** @file
+  This library is TPM2 device router. Platform can register multi TPM2 instance to it
+  via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.
+  At most one TPM2 instance can be finally registered, and other will return unsupported.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Protocol/AmdPspFtpmProtocol.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+PSP_FTPM_PROTOCOL  *PspFtpmProtocol;
+extern EFI_GUID    gAmdPspFtpmProtocolGuid;
+
+/**
+  The constructor function for this library.
+
+  @param  None
+
+  @retval EFI_SUCCESS   This library is ready for use.
+
+**/
+EFI_STATUS
+EFIAPI
+Tpm2DeviceLibConstructor (
+  VOID
+  )
+{
+  return gBS->LocateProtocol (&gAmdPspFtpmProtocolGuid, NULL, (VOID **)&PspFtpmProtocol);
+}
+
+/**
+  This service enables the sending of commands to the TPM2.
+
+  @param[in]  InputParameterBlockSize  Size of the TPM2 input parameter block.
+  @param[in]  InputParameterBlock      Pointer to the TPM2 input parameter block.
+  @param[in]  OutputParameterBlockSize Size of the TPM2 output parameter block.
+  @param[in]  OutputParameterBlock     Pointer to the TPM2 output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+
+  if ((NULL == InputParameterBlock) || (NULL == OutputParameterBlock) || (0 == InputParameterBlockSize)) {
+    DEBUG ((DEBUG_ERROR, "Buffer == NULL or InputParameterBlockSize == 0\n"));
+    Status = EFI_INVALID_PARAMETER;
+    return Status;
+  }
+
+  Status = PspFtpmProtocol->Execute (
+                              PspFtpmProtocol,
+                              (VOID *)InputParameterBlock,
+                              InputParameterBlockSize,
+                              (VOID *)OutputParameterBlock,
+                              OutputParameterBlockSize
+                              );
+
+  return Status;
+}
+
+/**
+  This service requests use TPM2.
+
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.
+  @retval EFI_NOT_FOUND    TPM2 not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RequestUseTpm (
+  VOID
+  )
+{
+  FTPM_INFO  FtpmStatus;
+
+  return PspFtpmProtocol->GetInfo (PspFtpmProtocol, &FtpmStatus);
+}
+
+/**
+  This service register TPM2 device.
+
+  @Param Tpm2Device  TPM2 device
+
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RegisterTpm2DeviceLib (
+  IN TPM2_DEVICE_INTERFACE  *Tpm2Device
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
new file mode 100644
index 0000000000..6708abdfce
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/DxeTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
@@ -0,0 +1,48 @@
+## @file
+#  Provides TPM 2.0 TIS functions
+#
+#  This library is TPM 2.0 device router. Platform can register multi TPM 2.0 instance to
+#  it via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.
+#  At most one TPM 2.0 instance can be finally registered, and other will return unsupported.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tpm2DeviceLibFtpm
+  FILE_GUID                      = E98C81D3-B90D-4D28-AB48-A207C89D44C0
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Tpm2DeviceLib | DXE_DRIVER DXE_RUNTIME_DRIVER
+  CONSTRUCTOR                    = Tpm2DeviceLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources.common]
+  Tpm2DeviceLibFtpm.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+
+[Protocols]
+  gAmdPspFtpmProtocolGuid
+
+[Depex]
+  gAmdPspFtpmProtocolGuid
\ No newline at end of file
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
new file mode 100644
index 0000000000..9e8cb5588d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.c
@@ -0,0 +1,141 @@
+/** @file
+  This library is TPM2 device router. Platform can register multi TPM2 instance to it
+  via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.
+  At most one TPM2 instance can be finally registered, and other will return unsupported.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Pi/PiPeiCis.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Ppi/AmdPspFtpmPpi.h>
+
+/**
+  The constructor function for this library.
+
+  @param  None
+
+  @retval EFI_SUCCESS   This library is ready for use.
+
+**/
+
+extern EFI_GUID  gAmdPspFtpmPpiGuid;
+
+EFI_STATUS
+EFIAPI
+Tpm2DeviceLibConstructor (
+  VOID
+  )
+{
+  PSP_FTPM_PPI  *PspFtpmPpi;
+
+  return (*GetPeiServicesTablePointer ())->LocatePpi (
+                                             GetPeiServicesTablePointer (),
+                                             &gAmdPspFtpmPpiGuid,
+                                             0,
+                                             NULL,
+                                             (VOID **)&PspFtpmPpi
+                                             );
+}
+
+/**
+  This service enables the sending of commands to the TPM2.
+
+  @param[in]  InputParameterBlockSize  Size of the TPM2 input parameter block.
+  @param[in]  InputParameterBlock      Pointer to the TPM2 input parameter block.
+  @param[in]  OutputParameterBlockSize Size of the TPM2 output parameter block.
+  @param[in]  OutputParameterBlock     Pointer to the TPM2 output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+
+  if ((NULL == InputParameterBlock) || (NULL == OutputParameterBlock) || (0 == InputParameterBlockSize)) {
+    DEBUG ((DEBUG_ERROR, "Buffer == NULL or InputParameterBlockSize == 0\n"));
+    Status = EFI_INVALID_PARAMETER;
+    return Status;
+  }
+
+  PSP_FTPM_PPI  *PspFtpmPpi;
+
+  Status = (*GetPeiServicesTablePointer ())->LocatePpi (
+                                               GetPeiServicesTablePointer (),
+                                               &gAmdPspFtpmPpiGuid,
+                                               0,
+                                               NULL,
+                                               (VOID **)&PspFtpmPpi
+                                               );
+  if (!EFI_ERROR (Status)) {
+    Status = PspFtpmPpi->Execute (
+                           PspFtpmPpi,
+                           (VOID *)InputParameterBlock,
+                           InputParameterBlockSize,
+                           (VOID *)OutputParameterBlock,
+                           OutputParameterBlockSize
+                           );
+  }
+
+  return Status;
+}
+
+/**
+  This service requests use TPM2.
+
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.
+  @retval EFI_NOT_FOUND    TPM2 not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RequestUseTpm (
+  VOID
+  )
+{
+  UINTN         FtpmStatus;
+  PSP_FTPM_PPI  *PspFtpmPpi;
+  EFI_STATUS    Status = (*GetPeiServicesTablePointer ())->LocatePpi (
+                                                             GetPeiServicesTablePointer (),
+                                                             &gAmdPspFtpmPpiGuid,
+                                                             0,
+                                                             NULL,
+                                                             (VOID **)&PspFtpmPpi
+                                                             );
+
+  return Status || PspFtpmPpi->CheckStatus (PspFtpmPpi, &FtpmStatus);
+}
+
+/**
+  This service register TPM2 device.
+
+  @Param Tpm2Device  TPM2 device
+
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RegisterTpm2DeviceLib (
+  IN TPM2_DEVICE_INTERFACE  *Tpm2Device
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
new file mode 100644
index 0000000000..a38ada3efd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/PeiTpm2DeviceLibFsp/Tpm2DeviceLibFtpm.inf
@@ -0,0 +1,47 @@
+## @file
+#  Provides TPM 2.0 TIS functions
+#
+#  This library is TPM 2.0 device router. Platform can register multi TPM 2.0 instance to
+#  it via PcdTpmInstanceGuid. Platform need make choice that which one will be final one.
+#  At most one TPM 2.0 instance can be finally registered, and other will return unsupported.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tpm2DeviceLibFtpm
+  FILE_GUID                      = 2E230843-274F-4C14-A4B5-46B6167E7A5C
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Tpm2DeviceLib | PEIM
+  CONSTRUCTOR                    = Tpm2DeviceLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources.common]
+  Tpm2DeviceLibFtpm.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+
+[Ppis]
+  gAmdPspFtpmPpiGuid
+
+[Depex]
+  gAmdPspFtpmPpiGuid
\ No newline at end of file
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c
new file mode 100644
index 0000000000..713c87a1ca
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.c
@@ -0,0 +1,108 @@
+/** @file
+  This library is TPM2 TCG2 protocol lib.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved. <BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/AmdPspFtpmLib.h>
+
+/**
+  The constructor function for this library.
+
+  @param  None
+
+  @retval EFI_SUCCESS   This library is ready for use.
+
+**/
+EFI_STATUS
+EFIAPI
+Tpm2DeviceLibConstructor (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This service enables the sending of commands to the TPM2.
+
+  @param[in]  InputParameterBlockSize  Size of the TPM2 input parameter block.
+  @param[in]  InputParameterBlock      Pointer to the TPM2 input parameter block.
+  @param[in]  OutputParameterBlockSize Size of the TPM2 output parameter block.
+  @param[in]  OutputParameterBlock     Pointer to the TPM2 output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2SubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+
+  if ((NULL == InputParameterBlock) || (NULL == OutputParameterBlock) || (0 == InputParameterBlockSize)) {
+    DEBUG ((DEBUG_ERROR, "Buffer == NULL or InputParameterBlockSize == 0\n"));
+    Status = EFI_INVALID_PARAMETER;
+    return Status;
+  }
+
+  Status = FtpmExecuteCommand (
+             (VOID *)InputParameterBlock,
+             InputParameterBlockSize,
+             (VOID *)OutputParameterBlock,
+             OutputParameterBlockSize
+             );
+
+  return Status;
+}
+
+/**
+  This service requests use TPM2.
+
+  @retval EFI_SUCCESS      Get the control of TPM2 chip.
+  @retval EFI_NOT_FOUND    TPM2 not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RequestUseTpm (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       FtpmStatus;
+
+  Status = FtpmGetInfo (&FtpmStatus);
+  return Status;
+}
+
+/**
+  This service register TPM2 device.
+
+  @Param Tpm2Device  TPM2 device
+
+  @retval EFI_SUCCESS          This TPM2 device is registered successfully.
+  @retval EFI_UNSUPPORTED      System does not support register this TPM2 device.
+  @retval EFI_ALREADY_STARTED  System already register this TPM2 device.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2RegisterTpm2DeviceLib (
+  IN TPM2_DEVICE_INTERFACE  *Tpm2Device
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf
new file mode 100644
index 0000000000..7e42703347
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2DeviceLib/Tpm2DeviceLibFtpm.inf
@@ -0,0 +1,43 @@
+## @file
+#  Provides function interfaces to communicate with TPM 2.0 device
+#
+#  This library helps to use TPM 2.0 device in library function API
+#  based on TPM2 protocol.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tpm2DeviceLibFtpm
+  FILE_GUID                      = 1E0C813B-46F5-4578-AA2D-E0AFFD89F2F9
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Tpm2DeviceLib
+  CONSTRUCTOR                    = Tpm2DeviceLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources.common]
+  Tpm2DeviceLibFtpm.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  AmdPspFtpmLib
+
+[Depex]
+  TRUE
\ No newline at end of file
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpm.inf
new file mode 100644
index 0000000000..2b957fd942
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpm.inf
@@ -0,0 +1,53 @@
+## @file
+#  AMD Ftpm 2.0 Instance Library Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tpm2InstanceLibAmdFtpm
+  FILE_GUID                      = F1FA6737-93AC-4B72-8906-3EAE247CFF8D
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NULL
+  CONSTRUCTOR                    = Tpm2InstanceLibAmdFTpmConstructor
+
+[Sources.IA32]
+  Tpm2InstanceLibAmdFTpmPei.c
+
+[Sources.X64]
+  Tpm2InstanceLibAmdFTpmDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses.X64]
+  UefiBootServicesTableLib
+
+[LibraryClasses.IA32]
+  PeiServicesLib
+
+[Protocols.X64]
+  gAmdPspFtpmProtocolGuid
+
+[Ppis.IA32]
+  gAmdPspFtpmPpiGuid
+  gAmdPspFtpmFactoryResetPpiGuid
+
+[Guids]
+  gEfiTpmDeviceInstanceNoneGuid
+
+[Pcd]
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdPspSystemTpmConfig
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid
+
+[Depex.IA32]
+  TRUE
+
+[Depex.X64]
+  TRUE
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmDxe.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmDxe.c
new file mode 100644
index 0000000000..af9bf81c18
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmDxe.c
@@ -0,0 +1,109 @@
+/** @file
+  Implements Tpm2InstanceLibAmdFTpmDxe.C
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/PcdLib.h>
+#include <Protocol/AmdPspFtpmProtocol.h>
+#include <Library/AmdPspFtpmLib.h>
+
+// gEfiTpmDeviceInstanceTpm20AmdFtpmGuid
+#define TPM_DEVICE_INTERFACE_TPM20_AMD_FTPM  \
+  {0x286bf25a, 0xc2c3, 0x408c, {0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17}}
+
+PSP_FTPM_PROTOCOL  *mfTpmProtocol = NULL;
+
+/**
+  This service enables the sending of commands to the FTPM.
+
+  @param[in]      InputParameterBlockSize  Size of the FTPM input parameter block.
+  @param[in]      InputParameterBlock      Pointer to the FTPM input parameter block.
+  @param[in,out]  OutputParameterBlockSize Size of the FTPM output parameter block.
+  @param[in]      OutputParameterBlock     Pointer to the FTPM output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+FTpmSubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  return mfTpmProtocol->Execute (mfTpmProtocol, InputParameterBlock, InputParameterBlockSize, OutputParameterBlock, OutputParameterBlockSize);
+}
+
+/**
+  This service requests use FTPM.
+
+  @retval EFI_SUCCESS      Get the control of FTPM chip.
+  @retval EFI_NOT_FOUND    FTPM not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+FTpmRequestUseTpm (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       fTpmStatus;
+
+  if ((PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_PSP_FTPM) ||
+      (PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_HSP_FTPM))
+  {
+    Status = mfTpmProtocol->CheckStatus (mfTpmProtocol, &fTpmStatus);
+    DEBUG ((DEBUG_INFO, "fTPM Status = %r\n", Status));
+    return Status;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+TPM2_DEVICE_INTERFACE  mFTpmInternalTpm2Device = {
+  TPM_DEVICE_INTERFACE_TPM20_AMD_FTPM,
+  FTpmSubmitCommand,
+  FTpmRequestUseTpm,
+};
+
+/**
+  The function register FTPM instance.
+
+  @retval EFI_SUCCESS   FTPM instance is registered, or system dose not surpport registr FTPM instance
+**/
+EFI_STATUS
+EFIAPI
+Tpm2InstanceLibAmdFTpmConstructor (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->LocateProtocol (
+                  &gAmdPspFtpmProtocolGuid,
+                  NULL,
+                  (VOID **)&mfTpmProtocol
+                  );
+  if (Status == EFI_SUCCESS) {
+    Status = Tpm2RegisterTpm2DeviceLib (&mFTpmInternalTpm2Device);
+    if (Status == EFI_UNSUPPORTED) {
+      //
+      // Unsupported means platform policy does not need this instance enabled.
+      //
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmPei.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmPei.c
new file mode 100644
index 0000000000..35671644e2
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/AmdFtpm/Tpm2InstanceLibAmdFTpm/Tpm2InstanceLibAmdFTpmPei.c
@@ -0,0 +1,153 @@
+/** @file
+  Implements Tpm2InstanceLibAmdFTpmPei.C
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/PcdLib.h>
+#include <Ppi/AmdPspFtpmPpi.h>
+#include <Library/AmdPspFtpmLib.h>
+#include <Guid/TpmInstance.h>
+
+// gEfiTpmDeviceInstanceTpm20AmdFtpmGuid
+#define TPM_DEVICE_INTERFACE_TPM20_AMD_FTPM  \
+  {0x286bf25a, 0xc2c3, 0x408c, {0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17}}
+
+/**
+ * @brief gAmdFtpmFactoryResetPpiGuid callback, disable TPM
+ *
+ * @param PeiServices
+ * @param NotifyDesc
+ * @param InvokePpi
+ * @return EFI_STATUS
+ */
+EFI_STATUS
+EFIAPI
+AmdFtpmFactoryResetCallback (
+  IN  EFI_PEI_SERVICES           **PeiServices,
+  IN  EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
+  IN  VOID                       *InvokePpi
+  )
+{
+  UINTN       Size;
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "AmdFtpmFactoryResetCallback\n"));
+  // gEfiTpmDeviceInstanceNoneGuid GUID value used for PcdTpmInstanceGuid to indicate TPM is disabled.
+  Size   = sizeof (gEfiTpmDeviceInstanceNoneGuid);
+  Status = PcdSetPtrS (PcdTpmInstanceGuid, &Size, &gEfiTpmDeviceInstanceNoneGuid);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
+EFI_PEI_NOTIFY_DESCRIPTOR  mAmdFtpmFactoryResetPpiCallback = {
+  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+  &gAmdPspFtpmFactoryResetPpiGuid,
+  AmdFtpmFactoryResetCallback
+};
+
+/**
+  This service enables the sending of commands to the FTPM.
+
+  @param[in]      InputParameterBlockSize  Size of the FTPM input parameter block.
+  @param[in]      InputParameterBlock      Pointer to the FTPM input parameter block.
+  @param[in,out]  OutputParameterBlockSize Size of the FTPM output parameter block.
+  @param[in]      OutputParameterBlock     Pointer to the FTPM output parameter block.
+
+  @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
+  @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
+  @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
+**/
+EFI_STATUS
+EFIAPI
+FTpmSubmitCommand (
+  IN UINT32      InputParameterBlockSize,
+  IN UINT8       *InputParameterBlock,
+  IN OUT UINT32  *OutputParameterBlockSize,
+  IN UINT8       *OutputParameterBlock
+  )
+{
+  PSP_FTPM_PPI  *AmdFtpmPpi;
+  EFI_STATUS    Status;
+
+  Status = PeiServicesLocatePpi (&gAmdPspFtpmPpiGuid, 0, NULL, (VOID **)&AmdFtpmPpi);
+  if (Status == EFI_SUCCESS) {
+    return AmdFtpmPpi->Execute (AmdFtpmPpi, InputParameterBlock, InputParameterBlockSize, OutputParameterBlock, OutputParameterBlockSize);
+  }
+
+  return Status;
+}
+
+/**
+  This service requests use FTPM.
+
+  @retval EFI_SUCCESS      Get the control of FTPM chip.
+  @retval EFI_NOT_FOUND    FTPM not found.
+  @retval EFI_DEVICE_ERROR Unexpected device behavior.
+**/
+EFI_STATUS
+EFIAPI
+FTpmRequestUseTpm (
+  VOID
+  )
+{
+  if ((PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_PSP_FTPM) ||
+      (PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_HSP_FTPM))
+  {
+    // @todo Test fTPM functionality
+    DEBUG ((DEBUG_INFO, "fTPM is used\n"));
+    return EFI_SUCCESS;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+TPM2_DEVICE_INTERFACE  mFTpmInternalTpm2Device = {
+  TPM_DEVICE_INTERFACE_TPM20_AMD_FTPM,
+  FTpmSubmitCommand,
+  FTpmRequestUseTpm,
+};
+
+/**
+  The function register FTPM instance.
+
+  @retval EFI_SUCCESS   FTPM instance is registered, or system dose not surpport registr FTPM instance
+**/
+EFI_STATUS
+EFIAPI
+Tpm2InstanceLibAmdFTpmConstructor (
+  VOID
+  )
+{
+  EFI_STATUS    Status;
+  PSP_FTPM_PPI  *AmdFtpmPpi;
+
+  if ((PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_PSP_FTPM) ||
+      (PcdGet8 (PcdAmdPspSystemTpmConfig) == SYSTEM_TPM_CONFIG_HSP_FTPM))
+  {
+    //
+    // AMD HSP f-TPM for EDK2 Core Base, Get the HSP PSP TcgEvetLog before BIOS
+    //
+    Status = PeiServicesLocatePpi (&gAmdPspFtpmPpiGuid, 0, NULL, (VOID **)&AmdFtpmPpi);
+    if (Status == EFI_SUCCESS) {
+      Status = Tpm2RegisterTpm2DeviceLib (&mFTpmInternalTpm2Device);
+      if (Status == EFI_UNSUPPORTED) {
+        //
+        // Unsupported means platform policy does not need this instance enabled.
+        //
+        return EFI_SUCCESS;
+      }
+    }
+
+    PeiServicesNotifyPpi (&mAmdFtpmFactoryResetPpiCallback);
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
new file mode 100644
index 0000000000..28b945fbba
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.c
@@ -0,0 +1,1269 @@
+/** @file
+  Execute pending TPM2 requests from OS or BIOS.
+
+  Caution: This module requires additional review when modified.
+  This driver will have external input - variable.
+  This external input must be validated carefully to avoid security issue.
+
+  Tpm2ExecutePendingTpmRequest() will receive untrusted input and do validation.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Protocol/Tcg2Protocol.h>
+#include <Protocol/VariableLock.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/HobLib.h>
+#include <Guid/EventGroup.h>
+#include <Guid/Tcg2PhysicalPresenceData.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+#include <Library/Tcg2PpVendorLib.h>
+
+#define CONFIRM_BUFFER_SIZE  4096
+
+EFI_HII_HANDLE  mTcg2PpStringPackHandle;
+
+/**
+  Get string by string id from HII Interface.
+
+  @param[in] Id          String ID.
+
+  @retval    CHAR16 *    String from ID.
+  @retval    NULL        If error occurs.
+
+**/
+CHAR16 *
+Tcg2PhysicalPresenceGetStringById (
+  IN  EFI_STRING_ID  Id
+  )
+{
+  return HiiGetString (mTcg2PpStringPackHandle, Id, NULL);
+}
+
+/**
+  Send ClearControl and Clear command to TPM.
+
+  @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
+
+  @retval EFI_SUCCESS           Operation completed successfully.
+  @retval EFI_TIMEOUT           The register can't run into the expected status in time.
+  @retval EFI_BUFFER_TOO_SMALL  Response data buffer is too small.
+  @retval EFI_DEVICE_ERROR      Unexpected device behavior.
+
+**/
+EFI_STATUS
+EFIAPI
+Tpm2CommandClear (
+  IN TPM2B_AUTH  *PlatformAuth  OPTIONAL
+  )
+{
+  EFI_STATUS         Status;
+  TPMS_AUTH_COMMAND  *AuthSession;
+  TPMS_AUTH_COMMAND  LocalAuthSession;
+
+  if (PlatformAuth == NULL) {
+    AuthSession = NULL;
+  } else {
+    AuthSession = &LocalAuthSession;
+    ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession));
+    LocalAuthSession.sessionHandle = TPM_RS_PW;
+    LocalAuthSession.hmac.size     = PlatformAuth->size;
+    CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
+  }
+
+  DEBUG ((DEBUG_INFO, "Tpm2ClearControl ... \n"));
+  Status = Tpm2ClearControl (TPM_RH_PLATFORM, AuthSession, NO);
+  DEBUG ((DEBUG_INFO, "Tpm2ClearControl - %r\n", Status));
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  DEBUG ((DEBUG_INFO, "Tpm2Clear ... \n"));
+  Status = Tpm2Clear (TPM_RH_PLATFORM, AuthSession);
+  DEBUG ((DEBUG_INFO, "Tpm2Clear - %r\n", Status));
+
+Done:
+  ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac));
+  return Status;
+}
+
+/**
+  Change EPS.
+
+  @param[in]  PlatformAuth      platform auth value. NULL means no platform auth change.
+
+  @retval EFI_SUCCESS Operation completed successfully.
+**/
+EFI_STATUS
+Tpm2CommandChangeEps (
+  IN TPM2B_AUTH  *PlatformAuth  OPTIONAL
+  )
+{
+  EFI_STATUS         Status;
+  TPMS_AUTH_COMMAND  *AuthSession;
+  TPMS_AUTH_COMMAND  LocalAuthSession;
+
+  if (PlatformAuth == NULL) {
+    AuthSession = NULL;
+  } else {
+    AuthSession = &LocalAuthSession;
+    ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession));
+    LocalAuthSession.sessionHandle = TPM_RS_PW;
+    LocalAuthSession.hmac.size     = PlatformAuth->size;
+    CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
+  }
+
+  Status = Tpm2ChangeEPS (TPM_RH_PLATFORM, AuthSession);
+  DEBUG ((DEBUG_INFO, "Tpm2ChangeEPS - %r\n", Status));
+
+  ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac));
+  return Status;
+}
+
+/**
+  Execute physical presence operation requested by the OS.
+
+  @param[in]      PlatformAuth        platform auth value. NULL means no platform auth change.
+  @param[in]      CommandCode         Physical presence operation value.
+  @param[in]      CommandParameter    Physical presence operation parameter.
+  @param[in, out] PpiFlags            The physical presence interface flags.
+
+  @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Unknown physical presence operation.
+  @retval TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE   Error occurred during sending command to TPM or
+                                                   receiving response from TPM.
+  @retval Others                                   Return code from the TPM device after command execution.
+**/
+UINT32
+Tcg2ExecutePhysicalPresence (
+  IN      TPM2B_AUTH *PlatformAuth, OPTIONAL
+  IN      UINT32                           CommandCode,
+  IN      UINT32                           CommandParameter,
+  IN OUT  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *PpiFlags
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_TCG2_EVENT_ALGORITHM_BITMAP  TpmHashAlgorithmBitmap;
+  UINT32                           ActivePcrBanks;
+
+  switch (CommandCode) {
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
+      Status = Tpm2CommandClear (PlatformAuth);
+      if (EFI_ERROR (Status)) {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      }
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
+      PpiFlags->PPFlags |= TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
+      PpiFlags->PPFlags &= ~TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
+      Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // PP spec requirements:
+      //    Firmware should check that all requested (set) hashing algorithms are supported with respective PCR banks.
+      //    Firmware has to ensure that at least one PCR banks is active.
+      // If not, an error is returned and no action is taken.
+      //
+      if ((CommandParameter == 0) || ((CommandParameter & (~TpmHashAlgorithmBitmap)) != 0)) {
+        DEBUG ((DEBUG_ERROR, "PCR banks %x to allocate are not supported by TPM. Skip operation\n", CommandParameter));
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      }
+
+      Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, CommandParameter);
+      if (EFI_ERROR (Status)) {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      }
+
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
+      Status = Tpm2CommandChangeEps (PlatformAuth);
+      if (EFI_ERROR (Status)) {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      }
+
+    case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
+      Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);
+      ASSERT_EFI_ERROR (Status);
+      Status = Tpm2PcrAllocateBanks (PlatformAuth, TpmHashAlgorithmBitmap, TpmHashAlgorithmBitmap);
+      if (EFI_ERROR (Status)) {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      }
+
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
+      PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
+      PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
+      PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
+      PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
+      PpiFlags->PPFlags |= TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
+      PpiFlags->PPFlags &= ~TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID;
+      return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+
+    default:
+      if (CommandCode <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
+        return TCG_PP_OPERATION_RESPONSE_SUCCESS;
+      } else {
+        return TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+      }
+  }
+}
+
+/**
+  Read the specified key for user confirmation.
+
+  @param[in]  CautionKey  If true,  F12 is used as confirm key;
+                          If false, F10 is used as confirm key.
+
+  @retval     TRUE        User confirmed the changes by input.
+  @retval     FALSE       User discarded the changes.
+**/
+BOOLEAN
+Tcg2ReadUserKey (
+  IN     BOOLEAN  CautionKey
+  )
+{
+  EFI_STATUS     Status;
+  EFI_INPUT_KEY  Key;
+  UINT16         InputKey;
+
+  InputKey = 0;
+  do {
+    Status = gBS->CheckEvent (gST->ConIn->WaitForKey);
+    if (!EFI_ERROR (Status)) {
+      Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+      if (Key.ScanCode == SCAN_ESC) {
+        InputKey = Key.ScanCode;
+      }
+
+      if ((Key.ScanCode == SCAN_F10) && !CautionKey) {
+        InputKey = Key.ScanCode;
+      }
+
+      if ((Key.ScanCode == SCAN_F12) && CautionKey) {
+        InputKey = Key.ScanCode;
+      }
+    }
+  } while (InputKey == 0);
+
+  if (InputKey != SCAN_ESC) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Fill Buffer With BootHashAlg.
+
+  @param[in] Buffer               Buffer to be filled.
+  @param[in] BufferSize           Size of buffer.
+  @param[in] BootHashAlg          BootHashAlg.
+
+**/
+VOID
+Tcg2FillBufferWithBootHashAlg (
+  IN UINT16  *Buffer,
+  IN UINTN   BufferSize,
+  IN UINT32  BootHashAlg
+  )
+{
+  Buffer[0] = 0;
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA1", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA384", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SHA512", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+
+  if ((BootHashAlg & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {
+    if (Buffer[0] != 0) {
+      StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L", ", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+    }
+
+    StrnCatS (Buffer, BufferSize / sizeof (CHAR16), L"SM3_256", (BufferSize / sizeof (CHAR16)) - StrLen (Buffer) - 1);
+  }
+}
+
+/**
+  Display the confirm text and get user confirmation.
+
+  @param[in] TpmPpCommand             The requested TPM physical presence command.
+  @param[in] TpmPpCommandParameter    The requested TPM physical presence command parameter.
+
+  @retval    TRUE          The user has confirmed the changes.
+  @retval    FALSE         The user doesn't confirm the changes.
+**/
+BOOLEAN
+Tcg2UserConfirm (
+  IN      UINT32  TpmPpCommand,
+  IN      UINT32  TpmPpCommandParameter
+  )
+{
+  CHAR16                            *ConfirmText;
+  CHAR16                            *TmpStr1;
+  CHAR16                            *TmpStr2;
+  UINTN                             BufSize;
+  BOOLEAN                           CautionKey;
+  BOOLEAN                           NoPpiInfo;
+  UINT16                            Index;
+  CHAR16                            DstStr[81];
+  CHAR16                            TempBuffer[1024];
+  CHAR16                            TempBuffer2[1024];
+  EFI_TCG2_PROTOCOL                 *Tcg2Protocol;
+  EFI_TCG2_BOOT_SERVICE_CAPABILITY  ProtocolCapability;
+  UINT32                            CurrentPCRBanks;
+  EFI_STATUS                        Status;
+
+  TmpStr2     = NULL;
+  CautionKey  = FALSE;
+  NoPpiInfo   = FALSE;
+  BufSize     = CONFIRM_BUFFER_SIZE;
+  ConfirmText = AllocateZeroPool (BufSize);
+  ASSERT (ConfirmText != NULL);
+
+  mTcg2PpStringPackHandle = HiiAddPackages (&gEfiTcg2PhysicalPresenceGuid, gImageHandle, DxeTcg2PhysicalPresenceLibStrings, NULL);
+  ASSERT (mTcg2PpStringPackHandle != NULL);
+
+  switch (TpmPpCommand) {
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
+      CautionKey = TRUE;
+      TmpStr2    = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
+      CautionKey = TRUE;
+      NoPpiInfo  = TRUE;
+      TmpStr2    = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CLEAR));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_PPI_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NOTE_CLEAR));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CLEAR));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n\n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
+      Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);
+      ASSERT_EFI_ERROR (Status);
+
+      ProtocolCapability.Size = sizeof (ProtocolCapability);
+      Status                  = Tcg2Protocol->GetCapability (
+                                                Tcg2Protocol,
+                                                &ProtocolCapability
+                                                );
+      ASSERT_EFI_ERROR (Status);
+
+      Status = Tcg2Protocol->GetActivePcrBanks (
+                               Tcg2Protocol,
+                               &CurrentPCRBanks
+                               );
+      ASSERT_EFI_ERROR (Status);
+
+      CautionKey = TRUE;
+      TmpStr2    = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_SET_PCR_BANKS));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_1));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_SET_PCR_BANKS_2));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      Tcg2FillBufferWithBootHashAlg (TempBuffer, sizeof (TempBuffer), TpmPpCommandParameter);
+      Tcg2FillBufferWithBootHashAlg (TempBuffer2, sizeof (TempBuffer2), CurrentPCRBanks);
+
+      TmpStr1 = AllocateZeroPool (BufSize);
+      ASSERT (TmpStr1 != NULL);
+      UnicodeSPrint (TmpStr1, BufSize, L"Current PCRBanks is 0x%x. (%s)\nNew PCRBanks is 0x%x. (%s)\n", CurrentPCRBanks, TempBuffer2, TpmPpCommandParameter, TempBuffer);
+
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), L" \n", (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
+      CautionKey = TRUE;
+      TmpStr2    = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CHANGE_EPS));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_1));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_WARNING_CHANGE_EPS_2));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
+      TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ENABLE_BLOCK_SID));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
+      TmpStr2 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_DISABLE_BLOCK_SID));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
+      NoPpiInfo = TRUE;
+      TmpStr2   = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_ENABLE_BLOCK_SID));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
+      NoPpiInfo = TRUE;
+      TmpStr2   = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PP_DISABLE_BLOCK_SID));
+
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_PPI_HEAD_STR));
+      UnicodeSPrint (ConfirmText, BufSize, TmpStr1, TmpStr2);
+      FreePool (TmpStr1);
+      break;
+
+    default:
+      ;
+  }
+
+  if (TmpStr2 == NULL) {
+    FreePool (ConfirmText);
+    return FALSE;
+  }
+
+  if (TpmPpCommand < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) {
+    if (CautionKey) {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_CAUTION_KEY));
+    } else {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_ACCEPT_KEY));
+    }
+
+    StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+    FreePool (TmpStr1);
+
+    if (NoPpiInfo) {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_NO_PPI_INFO));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+    }
+
+    TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TPM_REJECT_KEY));
+  } else {
+    if (CautionKey) {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_CAUTION_KEY));
+    } else {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_ACCEPT_KEY));
+    }
+
+    StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+    FreePool (TmpStr1);
+
+    if (NoPpiInfo) {
+      TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_NO_PPI_INFO));
+      StrnCatS (ConfirmText, BufSize / sizeof (CHAR16), TmpStr1, (BufSize / sizeof (CHAR16)) - StrLen (ConfirmText) - 1);
+      FreePool (TmpStr1);
+    }
+
+    TmpStr1 = Tcg2PhysicalPresenceGetStringById (STRING_TOKEN (TCG_STORAGE_REJECT_KEY));
+  }
+
+  BufSize -= StrSize (ConfirmText);
+  UnicodeSPrint (ConfirmText + StrLen (ConfirmText), BufSize, TmpStr1, TmpStr2);
+
+  DstStr[80] = L'\0';
+  for (Index = 0; Index < StrLen (ConfirmText); Index += 80) {
+    StrnCpyS (DstStr, sizeof (DstStr) / sizeof (CHAR16), ConfirmText + Index, sizeof (DstStr) / sizeof (CHAR16) - 1);
+    Print (DstStr);
+  }
+
+  FreePool (TmpStr1);
+  FreePool (TmpStr2);
+  FreePool (ConfirmText);
+  HiiRemovePackages (mTcg2PpStringPackHandle);
+
+  if (Tcg2ReadUserKey (CautionKey)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Check if there is a valid physical presence command request. Also updates parameter value
+  to whether the requested physical presence command already confirmed by user
+
+   @param[in]  TcgPpData                 EFI Tcg2 Physical Presence request data.
+   @param[in]  Flags                     The physical presence interface flags.
+   @param[out] RequestConfirmed          If the physical presence operation command required user confirm from UI.
+                                           True, it indicates the command doesn't require user confirm, or already confirmed
+                                                 in last boot cycle by user.
+                                           False, it indicates the command need user confirm from UI.
+
+   @retval  TRUE        Physical Presence operation command is valid.
+   @retval  FALSE       Physical Presence operation command is invalid.
+
+**/
+BOOLEAN
+Tcg2HaveValidTpmRequest  (
+  IN      EFI_TCG2_PHYSICAL_PRESENCE        *TcgPpData,
+  IN      EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags,
+  OUT     BOOLEAN                           *RequestConfirmed
+  )
+{
+  EFI_TCG2_PROTOCOL  *Tcg2Protocol;
+  EFI_STATUS         Status;
+  BOOLEAN            IsRequestValid;
+
+  *RequestConfirmed = FALSE;
+
+  if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
+    //
+    // Need TCG2 protocol.
+    //
+    Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);
+    if (EFI_ERROR (Status)) {
+      return FALSE;
+    }
+  }
+
+  switch (TcgPpData->PPRequest) {
+    case TCG2_PHYSICAL_PRESENCE_NO_ACTION:
+      *RequestConfirmed = TRUE;
+      return TRUE;
+
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
+      if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
+      *RequestConfirmed = TRUE;
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
+      if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
+      if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
+      *RequestConfirmed = TRUE;
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
+      if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
+      if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) {
+        *RequestConfirmed = TRUE;
+      }
+
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
+      *RequestConfirmed = TRUE;
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
+      break;
+
+    default:
+      if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+        IsRequestValid = Tcg2PpVendorLibHasValidRequest (TcgPpData->PPRequest, Flags.PPFlags, RequestConfirmed);
+        if (!IsRequestValid) {
+          return FALSE;
+        } else {
+          break;
+        }
+      } else {
+        //
+        // Wrong Physical Presence command
+        //
+        return FALSE;
+      }
+  }
+
+  if ((Flags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) != 0) {
+    //
+    // It had been confirmed in last boot, it doesn't need confirm again.
+    //
+    *RequestConfirmed = TRUE;
+  }
+
+  //
+  // Physical Presence command is correct
+  //
+  return TRUE;
+}
+
+/**
+  Check and execute the requested physical presence command.
+
+  Caution: This function may receive untrusted input.
+  TcgPpData variable is external input, so this function will validate
+  its data structure to be valid value.
+
+  @param[in]      PlatformAuth      platform auth value. NULL means no platform auth change.
+  @param[in, out] TcgPpData         Pointer to the physical presence NV variable.
+  @param[in, out] Flags             Pointer to the physical presence interface flags.
+**/
+VOID
+Tcg2ExecutePendingTpmRequest (
+  IN      TPM2B_AUTH *PlatformAuth, OPTIONAL
+  IN OUT  EFI_TCG2_PHYSICAL_PRESENCE       *TcgPpData,
+  IN OUT  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS *Flags
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             DataSize;
+  BOOLEAN                           RequestConfirmed;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  NewFlags;
+  BOOLEAN                           ResetRequired;
+  UINT32                            NewPPFlags;
+
+  if (TcgPpData->PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
+    //
+    // No operation request
+    //
+    return;
+  }
+
+  if (!Tcg2HaveValidTpmRequest (TcgPpData, *Flags, &RequestConfirmed)) {
+    //
+    // Invalid operation request.
+    //
+    if (TcgPpData->PPRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
+      TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_SUCCESS;
+    } else {
+      TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_BIOS_FAILURE;
+    }
+
+    TcgPpData->LastPPRequest      = TcgPpData->PPRequest;
+    TcgPpData->PPRequest          = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
+    TcgPpData->PPRequestParameter = 0;
+
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+    Status   = gRT->SetVariable (
+                      TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                      &gEfiTcg2PhysicalPresenceGuid,
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                      DataSize,
+                      TcgPpData
+                      );
+    return;
+  }
+
+  ResetRequired = FALSE;
+  if (TcgPpData->PPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+    NewFlags              = *Flags;
+    NewPPFlags            = NewFlags.PPFlags;
+    TcgPpData->PPResponse = Tcg2PpVendorLibExecutePendingRequest (PlatformAuth, TcgPpData->PPRequest, &NewPPFlags, &ResetRequired);
+    NewFlags.PPFlags      = NewPPFlags;
+  } else {
+    if (!RequestConfirmed) {
+      //
+      // Print confirm text and wait for approval.
+      //
+      DEBUG ((DEBUG_INFO, "Print confirm text and wait for approval.\n"));
+      RequestConfirmed = TRUE;
+      // RequestConfirmed = Tcg2UserConfirm (TcgPpData->PPRequest, TcgPpData->PPRequestParameter);
+    }
+
+    //
+    // Execute requested physical presence command
+    //
+    TcgPpData->PPResponse = TCG_PP_OPERATION_RESPONSE_USER_ABORT;
+    NewFlags              = *Flags;
+    if (RequestConfirmed) {
+      TcgPpData->PPResponse = Tcg2ExecutePhysicalPresence (
+                                PlatformAuth,
+                                TcgPpData->PPRequest,
+                                TcgPpData->PPRequestParameter,
+                                &NewFlags
+                                );
+    }
+  }
+
+  //
+  // Save the flags if it is updated.
+  //
+  if (CompareMem (Flags, &NewFlags, sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS)) != 0) {
+    *Flags = NewFlags;
+    Status = gRT->SetVariable (
+                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                    sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
+                    &NewFlags
+                    );
+  }
+
+  //
+  // Clear request
+  //
+  if ((NewFlags.PPFlags & TCG2_LIB_PP_FLAG_RESET_TRACK) == 0) {
+    TcgPpData->LastPPRequest      = TcgPpData->PPRequest;
+    TcgPpData->PPRequest          = TCG2_PHYSICAL_PRESENCE_NO_ACTION;
+    TcgPpData->PPRequestParameter = 0;
+  }
+
+  //
+  // Save changes
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->SetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                    DataSize,
+                    TcgPpData
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Fail to set variable %S, %r\n", TCG2_PHYSICAL_PRESENCE_VARIABLE, Status));
+    return;
+  }
+
+  if (TcgPpData->PPResponse == TCG_PP_OPERATION_RESPONSE_USER_ABORT) {
+    DEBUG ((DEBUG_INFO, "User abort the TPM action \n"));
+    return;
+  }
+
+  //
+  // Reset system to make new TPM settings in effect
+  //
+  switch (TcgPpData->LastPPRequest) {
+    case TCG2_PHYSICAL_PRESENCE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
+    case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
+    case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
+    case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
+    case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
+      break;
+
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
+    case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
+      return;
+
+    default:
+      if (TcgPpData->LastPPRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+        if (ResetRequired) {
+          break;
+        } else {
+          return;
+        }
+      }
+
+      if (TcgPpData->PPRequest != TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
+        break;
+      }
+
+      return;
+  }
+
+  // Print (L"Rebooting system to make TPM2 settings in effect\n");
+  DEBUG ((DEBUG_INFO, "Rebooting system to make TPM2 settings in effect\n"));
+  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+  ASSERT (FALSE);
+}
+
+/**
+  Check and execute the pending TPM request.
+
+  The TPM request may come from OS or BIOS. This API will display request information and wait
+  for user confirmation if TPM request exists. The TPM request will be sent to TPM device after
+  the TPM request is confirmed, and one or more reset may be required to make TPM request to
+  take effect.
+
+  This API should be invoked after console in and console out are all ready as they are required
+  to display request information and get user input to confirm the request.
+
+  @param[in]  PlatformAuth                   platform auth value. NULL means no platform auth change.
+**/
+VOID
+EFIAPI
+Tcg2PhysicalPresenceLibProcessRequest (
+  IN      TPM2B_AUTH  *PlatformAuth  OPTIONAL
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             DataSize;
+  EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;
+  EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
+
+  //
+  // This flags variable controls whether physical presence is required for TPM command.
+  // It should be protected from malicious software. We set it as read-only variable here.
+  //
+  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
+  if (!EFI_ERROR (Status)) {
+    Status = VariableLockProtocol->RequestToLock (
+                                     VariableLockProtocol,
+                                     TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                                     &gEfiTcg2PhysicalPresenceGuid
+                                     );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "[TPM2] Error when lock variable %s, Status = %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));
+      ASSERT_EFI_ERROR (Status);
+    }
+  }
+
+  // On AMD FCH, always do S4 for shutdown.
+  // Todo: Chang to PCD method for this
+  //
+  // Check S4 resume
+  //
+  //  if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
+  //    DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n"));
+  //    return ;
+  //  }
+
+  //
+  // Initialize physical presence flags.
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpiFlags
+                    );
+  if (EFI_ERROR (Status)) {
+    PpiFlags.PPFlags = PcdGet32 (PcdTcg2PhysicalPresenceFlags);
+    Status           = gRT->SetVariable (
+                              TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                              &gEfiTcg2PhysicalPresenceGuid,
+                              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                              sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS),
+                              &PpiFlags
+                              );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "[TPM2] Set physical presence flag failed, Status = %r\n", Status));
+      return;
+    }
+
+    DEBUG ((DEBUG_INFO, "[TPM2] Initial physical presence flags value is 0x%x\n", PpiFlags.PPFlags));
+  }
+
+  //
+  // Initialize physical presence variable.
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &TcgPpData
+                    );
+  if (EFI_ERROR (Status)) {
+    ZeroMem ((VOID *)&TcgPpData, sizeof (TcgPpData));
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+    Status   = gRT->SetVariable (
+                      TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                      &gEfiTcg2PhysicalPresenceGuid,
+                      EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                      DataSize,
+                      &TcgPpData
+                      );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "[TPM2] Set physical presence variable failed, Status = %r\n", Status));
+      return;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "[TPM2] Flags=%x, PPRequest=%x (LastPPRequest=%x)\n", PpiFlags.PPFlags, TcgPpData.PPRequest, TcgPpData.LastPPRequest));
+
+  //
+  // Execute pending TPM request.
+  //
+  Tcg2ExecutePendingTpmRequest (PlatformAuth, &TcgPpData, &PpiFlags);
+  DEBUG ((DEBUG_INFO, "[TPM2] PPResponse = %x (LastPPRequest=%x, Flags=%x)\n", TcgPpData.PPResponse, TcgPpData.LastPPRequest, PpiFlags.PPFlags));
+}
+
+/**
+  Check if the pending TPM request needs user input to confirm.
+
+  The TPM request may come from OS. This API will check if TPM request exists and need user
+  input to confirmation.
+
+  @retval    TRUE        TPM needs input to confirm user physical presence.
+  @retval    FALSE       TPM doesn't need input to confirm user physical presence.
+
+**/
+BOOLEAN
+EFIAPI
+Tcg2PhysicalPresenceLibNeedUserConfirm (
+  VOID
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_TCG2_PHYSICAL_PRESENCE        TcgPpData;
+  UINTN                             DataSize;
+  BOOLEAN                           RequestConfirmed;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
+
+  // In AMD FCH, always do S4 for Shutdown.
+  // Todo: Chang to PCD method for this
+  //
+  // Check S4 resume
+  //
+  //  if (GetBootModeHob () == BOOT_ON_S4_RESUME) {
+  //    DEBUG ((DEBUG_INFO, "S4 Resume, Skip TPM PP process!\n"));
+  //    return FALSE;
+  //  }
+
+  //
+  // Check Tpm requests
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &TcgPpData
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[TPM2] GetVariable %S, %r\n", TCG2_PHYSICAL_PRESENCE_VARIABLE, Status));
+    return FALSE;
+  }
+
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpiFlags
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[TPM2] GetVariable %S, %r\n", TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));
+    return FALSE;
+  }
+
+  if (TcgPpData.PPRequest == TCG2_PHYSICAL_PRESENCE_NO_ACTION) {
+    //
+    // No operation request
+    //
+    return FALSE;
+  }
+
+  if (!Tcg2HaveValidTpmRequest (&TcgPpData, PpiFlags, &RequestConfirmed)) {
+    //
+    // Invalid operation request.
+    //
+    return FALSE;
+  }
+
+  if (!RequestConfirmed) {
+    //
+    // Need UI to confirm
+    //
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  The handler for TPM physical presence function:
+  Return TPM Operation Response to OS Environment.
+
+  @param[out]     MostRecentRequest Most recent operation request.
+  @param[out]     Response          Response to the most recent operation request.
+
+  @return Return Code for Return TPM Operation Response to OS Environment.
+**/
+UINT32
+EFIAPI
+Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
+  OUT UINT32  *MostRecentRequest,
+  OUT UINT32  *Response
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       DataSize;
+  EFI_TCG2_PHYSICAL_PRESENCE  PpData;
+
+  DEBUG ((DEBUG_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
+
+  //
+  // Get the Physical Presence variable
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpData
+                    );
+  if (EFI_ERROR (Status)) {
+    *MostRecentRequest = 0;
+    *Response          = 0;
+    DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
+    return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
+  }
+
+  *MostRecentRequest = PpData.LastPPRequest;
+  *Response          = PpData.PPResponse;
+
+  return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
+}
+
+/**
+  The handler for TPM physical presence function:
+  Submit TPM Operation Request to Pre-OS Environment and
+  Submit TPM Operation Request to Pre-OS Environment 2.
+
+  Caution: This function may receive untrusted input.
+
+  @param[in]      OperationRequest TPM physical presence operation request.
+  @param[in]      RequestParameter TPM physical presence operation request parameter.
+
+  @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
+          Submit TPM Operation Request to Pre-OS Environment 2.
+**/
+UINT32
+EFIAPI
+Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
+  IN UINT32  OperationRequest,
+  IN UINT32  RequestParameter
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             DataSize;
+  EFI_TCG2_PHYSICAL_PRESENCE        PpData;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  Flags;
+
+  DEBUG ((DEBUG_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", OperationRequest, RequestParameter));
+
+  //
+  // Get the Physical Presence variable
+  //
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpData
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
+    return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
+  }
+
+  if ((OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
+      (OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN))
+  {
+    return TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
+  }
+
+  if ((PpData.PPRequest != OperationRequest) ||
+      (PpData.PPRequestParameter != RequestParameter))
+  {
+    PpData.PPRequest          = (UINT8)OperationRequest;
+    PpData.PPRequestParameter = RequestParameter;
+    DataSize                  = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+    Status                    = gRT->SetVariable (
+                                       TCG2_PHYSICAL_PRESENCE_VARIABLE,
+                                       &gEfiTcg2PhysicalPresenceGuid,
+                                       EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                                       DataSize,
+                                       &PpData
+                                       );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
+      return TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
+    }
+  }
+
+  if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+    DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+    Status   = gRT->GetVariable (
+                      TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                      &gEfiTcg2PhysicalPresenceGuid,
+                      NULL,
+                      &DataSize,
+                      &Flags
+                      );
+    if (EFI_ERROR (Status)) {
+      Flags.PPFlags = PcdGet32 (PcdTcg2PhysicalPresenceFlags);
+    }
+
+    return Tcg2PpVendorLibSubmitRequestToPreOSFunction (OperationRequest, Flags.PPFlags, RequestParameter);
+  }
+
+  return TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
+}
+
+/**
+  Return TPM2 ManagementFlags set by PP interface.
+
+  @retval    ManagementFlags    TPM2 Management Flags.
+**/
+UINT32
+EFIAPI
+Tcg2PhysicalPresenceLibGetManagementFlags (
+  VOID
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_TCG2_PHYSICAL_PRESENCE_FLAGS  PpiFlags;
+  UINTN                             DataSize;
+
+  DEBUG ((DEBUG_INFO, "[TPM2] GetManagementFlags\n"));
+
+  DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+  Status   = gRT->GetVariable (
+                    TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+                    &gEfiTcg2PhysicalPresenceGuid,
+                    NULL,
+                    &DataSize,
+                    &PpiFlags
+                    );
+  if (EFI_ERROR (Status)) {
+    PpiFlags.PPFlags = PcdGet32 (PcdTcg2PhysicalPresenceFlags);
+  }
+
+  return PpiFlags.PPFlags;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
new file mode 100644
index 0000000000..2ce1133596
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf
@@ -0,0 +1,68 @@
+## @file
+#  Executes TPM 2.0 requests from OS or BIOS
+#
+#  This library will check and execute TPM 2.0 request from OS or BIOS. The request may
+#  ask for user confirmation before execution.
+#
+#  Caution: This module requires additional review when modified.
+#  This driver will have external input - variable.
+#  This external input must be validated carefully to avoid security issue.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeTcg2PhysicalPresenceLib
+  MODULE_UNI_FILE                = DxeTcg2PhysicalPresenceLib.uni
+  FILE_GUID                      = 7E507A86-DE8B-4AD3-BC4C-0498389098D3
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Tcg2PhysicalPresenceLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  DxeTcg2PhysicalPresenceLib.c
+  PhysicalPresenceStrings.uni
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+  MemoryAllocationLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiRuntimeServicesTableLib
+  BaseMemoryLib
+  DebugLib
+  PrintLib
+  HiiLib
+  HobLib
+  Tpm2CommandLib
+  Tcg2PpVendorLib
+
+[Protocols]
+  gEfiTcg2ProtocolGuid                 ## SOMETIMES_CONSUMES
+  gEdkiiVariableLockProtocolGuid       ## SOMETIMES_CONSUMES
+
+[Pcd]
+  gEfiSecurityPkgTokenSpaceGuid.PcdTcg2PhysicalPresenceFlags       ## SOMETIMES_CONSUMES
+
+[Guids]
+  ## SOMETIMES_CONSUMES ## HII
+  ## SOMETIMES_PRODUCES ## Variable:L"Tcg2PhysicalPresence"
+  ## SOMETIMES_CONSUMES ## Variable:L"Tcg2PhysicalPresence"
+  ## SOMETIMES_PRODUCES ## Variable:L"Tcg2PhysicalPresenceFlags"
+  ## SOMETIMES_CONSUMES ## Variable:L"Tcg2PhysicalPresenceFlags"
+  gEfiTcg2PhysicalPresenceGuid
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni
new file mode 100644
index 0000000000..d7e4af732b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.uni
@@ -0,0 +1,22 @@
+// /** @file
+// Executes TPM 2.0 requests from OS or BIOS
+//
+// This library will check and execute TPM 2.0 request from OS or BIOS. The request may
+// ask for user confirmation before execution.
+//
+// Caution: This module requires additional review when modified.
+// This driver will have external input - variable.
+// This external input must be validated carefully to avoid security issue.
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "Executes TPM 2.0 requests from OS or BIOS"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This library will check and execute TPM 2.0 request from OS or BIOS. The request may ask for user confirmation before execution.\n"
+                                                        "Caution: This module requires additional review when modified. This driver will have external input - variable. This external input must be validated carefully to avoid security issue."
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni
new file mode 100644
index 0000000000..70fa651455
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/PhysicalPresenceStrings.uni
@@ -0,0 +1,57 @@
+// /** @file
+// String definitions for TPM 2.0 physical presence confirm text.
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#langdef en-US "English"
+
+#string TPM_HEAD_STR                  #language en-US    "A configuration change was requested to %s this computer's TPM (Trusted Platform Module)\n\n"
+#string TPM_PPI_HEAD_STR              #language en-US    "A configuration change was requested to allow the Operating System to %s the computer's TPM (Trusted Platform Module) without asking for user confirmation in the future.\n\n"
+
+#string TPM_ACCEPT_KEY                #language en-US    "Press F10 "
+#string TPM_CAUTION_KEY               #language en-US    "Press F12 "
+#string TPM_REJECT_KEY                #language en-US    "to %s the TPM \nPress ESC to reject this change request and continue\n"
+
+#string TPM_ENABLE                    #language en-US    "enable"
+#string TPM_DISABLE                   #language en-US    "disable"
+#string TPM_CLEAR                     #language en-US    "clear"
+#string TPM_SET_PCR_BANKS                       #language en-US    "change the boot measurements to use PCR bank(s) of"
+#string TPM_CHANGE_EPS                          #language en-US    "clear and change identity of"
+#string TPM_DISABLE_ENDORSEMENT_ENABLE_STORAGE  #language en-US    "disable access to some secrets stored in"
+
+#string TPM_NO_PPI_MAINTAIN           #language en-US    "maintain"
+#string TPM_NO_PPI_TURN_ON            #language en-US    "turn on"
+#string TPM_NO_PPI_TURN_OFF           #language en-US    "turn off"
+#string TPM_NO_PPI_INFO               #language en-US    "to approve future Operating System requests "
+
+#string TPM_WARNING_DISABLE           #language en-US    "WARNING: Doing so might prevent security applications that rely on the TPM from functioning as expected.\n\n"
+#string TPM_WARNING_CLEAR             #language en-US    "WARNING: Clearing erases information stored on the TPM. You will lose all created keys and access to data encrypted by these keys. "
+#string TPM_NOTE_CLEAR                #language en-US    "NOTE: This action does not clear the TPM, but by approving this configuration change, future actions to clear the TPM will not require user confirmation.\n\n"
+#string TPM_WARNING_SET_PCR_BANKS_1                     #language en-US    "WARNING: Changing the PCR bank(s) of the boot measurements may prevent the Operating System from properly processing the measurements. Please check if your Operating System supports the new PCR bank(s).\n\n"
+#string TPM_WARNING_SET_PCR_BANKS_2                     #language en-US    "WARNING: Secrets in the TPM that are bound to the boot state of your machine may become unusable.\n\n"
+#string TPM_WARNING_CHANGE_EPS_1                        #language en-US    "WARNING: Clearing erases information stored on the TPM. You will lose all created keys and access to data encrypted with these keys.\n\n"
+#string TPM_WARNING_CHANGE_EPS_2                        #language en-US    "WARNING: Changing the identity of the TPM may require additional steps to establish trust into the new identity.\n\n"
+#string TPM_WARNING_PP_CHANGE_PCRS_FALSE                #language en-US    "WARNING: Allowing future changes to format of the boot measurement log may affect the Operating System.\n\n"
+#string TPM_WARNING_PP_CHANGE_EPS_FALSE_1               #language en-US    "WARNING: Allowing future changes to the TPM's firmware may affect the operation of the TPM and may erase information stored on the TPM.\n\n"
+#string TPM_WARNING_PP_CHANGE_EPS_FALSE_2               #language en-US    "You may lose all created keys and access to data encrypted by these keys.\n\n"
+#string TPM_WARNING_DISABLE_ENDORSEMENT_ENABLE_STORAGE  #language en-US    "WARNING: Doing so might prevent security applications that rely on the TPM from functioning as expected.\n\n"
+
+#string TCG_STORAGE_HEAD_STR                  #language en-US    "A configuration change was requested to %s on subsequent boots\n\n"
+#string TCG_STORAGE_PPI_HEAD_STR              #language en-US    "A configuration change was requested to allow the Operating System to %s without asking for user confirmation in the future.\n\n"
+
+#string TCG_STORAGE_ACCEPT_KEY                #language en-US    "Press F10 "
+#string TCG_STORAGE_CAUTION_KEY               #language en-US    "Press F12 "
+#string TCG_STORAGE_REJECT_KEY                #language en-US    "to %s\nPress ESC to reject this change request and continue\n"
+
+#string TCG_STORAGE_NO_PPI_INFO               #language en-US    "to approve future Operating System requests "
+
+#string TCG_STORAGE_ENABLE_BLOCK_SID          #language en-US    "issue a Block SID authentication command"
+#string TCG_STORAGE_DISABLE_BLOCK_SID         #language en-US    "disable issuing a Block SID authentication command"
+
+#string TCG_STORAGE_PP_ENABLE_BLOCK_SID       #language en-US    "enable blocking SID authentication"
+#string TCG_STORAGE_PP_DISABLE_BLOCK_SID      #language en-US    "disable blocking SID authentication"
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c
new file mode 100644
index 0000000000..62317165cb
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.c
@@ -0,0 +1,854 @@
+/** @file
+  It updates fTPM2 items in ACPI table and registers SMI2 callback
+  functions for Tcg2 physical presence, ClearMemory, and sample
+  for dTPM StartMethod.
+
+  Caution: This module requires additional review when modified.
+  This driver will have external input - variable and ACPINvs data in SMM mode.
+  This external input must be validated carefully to avoid security issue.
+
+  PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Tcg2Smm.h"
+
+TPM2_CONTROL_AREA  *mFtpmControlArea = NULL;
+
+EFI_TPM2_ACPI_TABLE  mTpm2AcpiTemplate = {
+  {
+    EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
+    sizeof (mTpm2AcpiTemplate),
+    EFI_TPM2_ACPI_TABLE_REVISION,
+    //
+    // Compiler initializes the remaining bytes to 0
+    // These fields should be filled in in production
+    //
+  },
+  0, // BIT0~15:  PlatformClass
+     // BIT16~31: Reserved
+  0,                                    // Control Area
+  EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod
+};
+
+EFI_SMM_VARIABLE_PROTOCOL  *mSmmVariable;
+TCG_NVS                    *mTcgNvs;
+
+/**
+  Software SMI callback for TPM physical presence which is called from ACPI method.
+
+  Caution: This function may receive untrusted input.
+  Variable and ACPINvs are external input, so this function will validate
+  its data structure to be valid value.
+
+  @param[in]      DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
+  @param[in]      Context         Points to an optional handler context which was specified when the
+                                  handler was registered.
+  @param[in, out] CommBuffer      A pointer to a collection of data in memory that will
+                                  be conveyed from a non-SMM environment into an SMM environment.
+  @param[in, out] CommBufferSize  The size of the CommBuffer.
+
+  @retval EFI_SUCCESS             The interrupt was handled successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PhysicalPresenceCallback (
+  IN EFI_HANDLE  DispatchHandle,
+  IN CONST VOID  *Context,
+  IN OUT VOID    *CommBuffer,
+  IN OUT UINTN   *CommBufferSize
+  )
+{
+  UINT32  MostRecentRequest;
+  UINT32  Response;
+  UINT32  OperationRequest;
+  UINT32  RequestParameter;
+
+  if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {
+    mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
+                                             &MostRecentRequest,
+                                             &Response
+                                             );
+    mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest;
+    mTcgNvs->PhysicalPresence.Response    = Response;
+    return EFI_SUCCESS;
+  } else if (  (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS)
+            || (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2))
+  {
+    OperationRequest                     = mTcgNvs->PhysicalPresence.Request;
+    RequestParameter                     = mTcgNvs->PhysicalPresence.RequestParameter;
+    mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
+                                             &OperationRequest,
+                                             &RequestParameter
+                                             );
+    mTcgNvs->PhysicalPresence.Request          = OperationRequest;
+    mTcgNvs->PhysicalPresence.RequestParameter = RequestParameter;
+  } else if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {
+    mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PPRequestUserConfirm);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Software SMI callback for MemoryClear which is called from ACPI method.
+
+  Caution: This function may receive untrusted input.
+  Variable and ACPINvs are external input, so this function will validate
+  its data structure to be valid value.
+
+  @param[in]      DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().
+  @param[in]      Context         Points to an optional handler context which was specified when the
+                                  handler was registered.
+  @param[in, out] CommBuffer      A pointer to a collection of data in memory that will
+                                  be conveyed from a non-SMM environment into an SMM environment.
+  @param[in, out] CommBufferSize  The size of the CommBuffer.
+
+  @retval EFI_SUCCESS             The interrupt was handled successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+MemoryClearCallback (
+  IN EFI_HANDLE  DispatchHandle,
+  IN CONST VOID  *Context,
+  IN OUT VOID    *CommBuffer,
+  IN OUT UINTN   *CommBufferSize
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       DataSize;
+  UINT8       MorControl;
+
+  mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;
+  if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {
+    MorControl = (UINT8)mTcgNvs->MemoryClear.Request;
+  } else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {
+    DataSize = sizeof (UINT8);
+    Status   = mSmmVariable->SmmGetVariable (
+                               MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+                               &gEfiMemoryOverwriteControlDataGuid,
+                               NULL,
+                               &DataSize,
+                               &MorControl
+                               );
+    if (EFI_ERROR (Status)) {
+      mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
+      return EFI_SUCCESS;
+    }
+
+    if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {
+      return EFI_SUCCESS;
+    }
+
+    MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;
+  }
+
+  DataSize = sizeof (UINT8);
+  Status   = mSmmVariable->SmmSetVariable (
+                             MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+                             &gEfiMemoryOverwriteControlDataGuid,
+                             EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+                             DataSize,
+                             &MorControl
+                             );
+  if (EFI_ERROR (Status)) {
+    mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Find the operation region in TCG ACPI table by given Name and Size,
+  and initialize it if the region is found.
+
+  @param[in, out] Table          The TPM item in ACPI table.
+  @param[in]      Name           The name string to find in TPM table.
+  @param[in]      Size           The size of the region to find.
+
+  @return                        The allocated address for the found region.
+
+**/
+VOID *
+AssignOpRegion (
+  EFI_ACPI_DESCRIPTION_HEADER  *Table,
+  UINT32                       Name,
+  UINT16                       Size
+  )
+{
+  EFI_STATUS            Status;
+  AML_OP_REGION_32_8    *OpRegion;
+  EFI_PHYSICAL_ADDRESS  MemoryAddress;
+
+  MemoryAddress = SIZE_4GB - 1;
+
+  //
+  // Patch some pointers for the ASL code before loading the SSDT.
+  //
+  for (OpRegion  = (AML_OP_REGION_32_8 *)(Table + 1);
+       OpRegion <= (AML_OP_REGION_32_8 *)((UINT8 *)Table + Table->Length);
+       OpRegion  = (AML_OP_REGION_32_8 *)((UINT8 *)OpRegion + 1))
+  {
+    if ((OpRegion->OpRegionOp  == AML_EXT_REGION_OP) &&
+        (OpRegion->NameString  == Name) &&
+        (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&
+        (OpRegion->BytePrefix  == AML_BYTE_PREFIX))
+    {
+      Status = gBS->AllocatePages (AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);
+      ASSERT_EFI_ERROR (Status);
+      ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);
+      OpRegion->RegionOffset = (UINT32)(UINTN)MemoryAddress;
+      OpRegion->RegionLen    = (UINT8)Size;
+      break;
+    }
+  }
+
+  return (VOID *)(UINTN)MemoryAddress;
+}
+
+/**
+  Find the fTPM Control Area operation region in TCG ACPI table by given Name and Size,
+  and initialize it if the region is found.
+
+  @param[in, out] Table            The TPM item in ACPI table.
+  @param[in]      Name             The name string to find in TPM table.
+  @param[in]      ControlAreaAddr  The Control Area address to set.
+  @param[in]      ControlAreaSize  The Control Area size to size.
+
+  @return                          The allocated address for the found region.
+
+**/
+EFI_STATUS
+PatchTpmControlAreaOpRegion (
+  EFI_ACPI_DESCRIPTION_HEADER  *Table,
+  UINT32                       Name,
+  UINT32                       ControlAreaAddr,
+  UINT8                        ControlAreaSize
+  )
+{
+  EFI_STATUS          Status    = EFI_NOT_FOUND;
+  AML_OP_REGION_32_8  *OpRegion = NULL;
+
+  //
+  // Patch some pointers for the ASL code before loading the SSDT.
+  //
+  for (OpRegion  = (AML_OP_REGION_32_8 *)(Table + 1);
+       OpRegion <= (AML_OP_REGION_32_8 *)((UINT8 *)Table + Table->Length);
+       OpRegion  = (AML_OP_REGION_32_8 *)((UINT8 *)OpRegion + 1))
+  {
+    if ((OpRegion->OpRegionOp  == AML_EXT_REGION_OP) &&
+        (OpRegion->NameString  == Name) &&
+        (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&
+        (OpRegion->BytePrefix  == AML_BYTE_PREFIX))
+    {
+      OpRegion->RegionOffset = ControlAreaAddr;
+      OpRegion->RegionLen    = ControlAreaSize;
+      Status                 = EFI_SUCCESS;
+      break;
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Patch the Memory32Fixed definitions in TCG ACPI table, and initialize their value for pre-defined signatures.
+
+  @param[in, out] Table          The TPM item in ACPI table.
+  @param[in]      CommandAddr    The Command Address to set for certain signature in Memory32Fixed.
+  @param[in]      ResponseAddr   The Response Address to set for certain signature in Memory32Fixed.
+
+  @return                        The allocated address for the found region.
+
+**/
+EFI_STATUS
+AssignMemory32Fixed (
+  EFI_ACPI_DESCRIPTION_HEADER  *Table,
+  UINT32                       CommandAddr,
+  UINT32                       ResponseAddr
+  )
+{
+  EFI_STATUS  Status              = EFI_NOT_FOUND;
+  UINT8       *TmpPtr             = NULL;
+  BOOLEAN     CommandAddrPatched  = FALSE;
+  BOOLEAN     ResponseAddrPatched = FALSE;
+
+  //
+  // Patch some pointers for the ASL code before loading the SSDT.
+  //
+  for (TmpPtr = (UINT8 *)Table; TmpPtr <= (UINT8 *)Table + Table->Length; ) {
+    if (*(UINT32 *)TmpPtr  == 0xA5A5A5A5) {
+      *(UINT32 *)TmpPtr  = CommandAddr;
+      CommandAddrPatched = TRUE;
+      TmpPtr             = TmpPtr + 4;
+    } else if (*(UINT32 *)TmpPtr  == 0xAAAAAAAA) {
+      *(UINT32 *)TmpPtr   = ResponseAddr;
+      ResponseAddrPatched = TRUE;
+      TmpPtr              = TmpPtr + 4;
+    } else if (CommandAddrPatched && ResponseAddrPatched) {
+      Status = EFI_SUCCESS;
+      break;
+    }
+
+    ++TmpPtr;
+  }
+
+  return Status;
+}
+
+/**
+  Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM
+ACPI table is "$PV".
+
+  @param[in, out] Table          The TPM item in ACPI table.
+  @param[in]      PPVer          Version string of Physical Presence interface supported by platform.
+
+  @return                        The allocated address for the found region.
+
+**/
+EFI_STATUS
+UpdatePPVersion (
+  EFI_ACPI_DESCRIPTION_HEADER  *Table,
+  CHAR8                        *PPVer
+  )
+{
+  EFI_STATUS  Status;
+  UINT8       *DataPtr;
+
+  //
+  // Patch some pointers for the ASL code before loading the SSDT.
+  //
+  for (DataPtr  = (UINT8 *)(Table + 1);
+       DataPtr <= (UINT8 *)((UINT8 *)Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);
+       DataPtr += 1)
+  {
+    if (AsciiStrCmp ((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {
+      Status = AsciiStrCpyS ((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);
+      DEBUG ((DEBUG_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));
+      return Status;
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch is determined by input
+  interrupt buffer size. BufferSize, PkgLength and interrupt descirptor in ByteList need to be patched
+
+  @param[in, out] Table            The TPM item in ACPI table.
+  @param[in]      IrqBuffer        Input new IRQ buffer.
+  @param[in]      IrqBuffserSize   Input new IRQ buffer size.
+  @param[out]     IsShortFormPkgLength   If _PRS returns Short length Package(ACPI spec 20.2.4).
+
+  @return                          patch status.
+
+**/
+EFI_STATUS
+UpdatePossibleResource (
+  IN OUT  EFI_ACPI_DESCRIPTION_HEADER  *Table,
+  IN      UINT32                       *IrqBuffer,
+  IN      UINT32                       IrqBuffserSize,
+  OUT     BOOLEAN                      *IsShortFormPkgLength
+  )
+{
+  UINT8   *DataPtr;
+  UINT8   *DataEndPtr;
+  UINT32  NewPkgLength;
+  UINT32  OrignalPkgLength;
+
+  NewPkgLength     = 0;
+  OrignalPkgLength = 0;
+  DataEndPtr       = NULL;
+
+  //
+  // Follow ACPI spec
+  //           6.4.3   Extend Interrupt Descriptor.
+  //           19.3.3 ASL Resource Template
+  //           20      AML specification
+  // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag
+  //
+  //  AML data is organized by following rule.
+  //  Code need to patch BufferSize and PkgLength and interrupt descirptor in ByteList
+  //
+  // =============  Buffer ====================
+  //           DefBuffer := BufferOp PkgLength BufferSize ByteList
+  //            BufferOp := 0x11
+  //
+  // ==============PkgLength==================
+  //          PkgLength := PkgLeadByte |
+  //                              <PkgLeadByte ByteData> |
+  //                              <PkgLeadByte ByteData ByteData> |
+  //                              <PkgLeadByte ByteData ByteData ByteData>
+  //
+  //       PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
+  //                               <bit 5-4: Only used if PkgLength <= 63 >
+  //                               <bit 3-0: Least significant package length nybble>
+  //
+  // ==============BufferSize==================
+  //        BufferSize := Integar
+  //           Integar := ByteConst|WordConst|DwordConst....
+  //
+  //           ByteConst := BytePrefix ByteData
+  //
+  // ==============ByteList===================
+  //          ByteList := ByteData ByteList
+  //
+  // =========================================
+
+  //
+  // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching
+  //
+  for (DataPtr  = (UINT8 *)(Table + 1);
+       DataPtr < (UINT8 *)((UINT8 *)Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
+       DataPtr += 1)
+  {
+    if (CompareMem (DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE) == 0) {
+      //
+      // Jump over object name & BufferOp
+      //
+      DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
+
+      if ((*DataPtr & (BIT7|BIT6)) == 0) {
+        OrignalPkgLength = (UINT32)*DataPtr;
+        DataEndPtr       = DataPtr + OrignalPkgLength;
+
+        //
+        // Jump over PkgLength = PkgLeadByte only
+        //
+        NewPkgLength++;
+
+        //
+        // Jump over BufferSize
+        //
+        if (*(DataPtr + 1) == AML_BYTE_PREFIX) {
+          NewPkgLength += 2;
+        } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {
+          NewPkgLength += 3;
+        } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {
+          NewPkgLength += 5;
+        } else {
+          ASSERT (FALSE);
+          return EFI_UNSUPPORTED;
+        }
+      } else {
+        ASSERT (FALSE);
+        return EFI_UNSUPPORTED;
+      }
+
+      //
+      // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
+      //
+      NewPkgLength += 19 + IrqBuffserSize;
+      if (NewPkgLength > 63) {
+        break;
+      }
+
+      if (NewPkgLength > OrignalPkgLength) {
+        ASSERT (FALSE);
+        return EFI_INVALID_PARAMETER;
+      }
+
+      //
+      // 1.1 Patch PkgLength
+      //
+      *DataPtr = (UINT8)NewPkgLength;
+
+      //
+      // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
+      //      It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.
+      //
+      *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);
+
+      //
+      // Notify _PRS to report short formed ResourceTemplate
+      //
+      *IsShortFormPkgLength = TRUE;
+
+      break;
+    }
+  }
+
+  //
+  // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching
+  //
+  if (NewPkgLength > 63) {
+    NewPkgLength     = 0;
+    OrignalPkgLength = 0;
+    for (DataPtr  = (UINT8 *)(Table + 1);
+         DataPtr < (UINT8 *)((UINT8 *)Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
+         DataPtr += 1)
+    {
+      if (CompareMem (DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE) == 0) {
+        //
+        // Jump over object name & BufferOp
+        //
+        DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
+
+        if ((*DataPtr & (BIT7|BIT6)) != 0) {
+          OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + (*DataPtr & 0x0F);
+          DataEndPtr       = DataPtr + OrignalPkgLength;
+          //
+          // Jump over PkgLength = PkgLeadByte + ByteData length
+          //
+          NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);
+
+          //
+          // Jump over BufferSize
+          //
+          if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {
+            NewPkgLength += 2;
+          } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {
+            NewPkgLength += 3;
+          } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {
+            NewPkgLength += 5;
+          } else {
+            ASSERT (FALSE);
+            return EFI_UNSUPPORTED;
+          }
+        } else {
+          ASSERT (FALSE);
+          return EFI_UNSUPPORTED;
+        }
+
+        //
+        // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2  Bytes)
+        //
+        NewPkgLength += 19 + IrqBuffserSize;
+
+        if (NewPkgLength > OrignalPkgLength) {
+          ASSERT (FALSE);
+          return EFI_INVALID_PARAMETER;
+        }
+
+        //
+        // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
+        //
+        *DataPtr       = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);
+        *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);
+
+        //
+        // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
+        //     It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.
+        //
+        *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) = (UINT8)(IrqBuffserSize + 19);
+
+        //
+        // Notify _PRS to report long formed ResourceTemplate
+        //
+        *IsShortFormPkgLength = FALSE;
+        break;
+      }
+    }
+  }
+
+  if (DataPtr >= (UINT8 *)((UINT8 *)Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE))) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // 3. Move DataPtr to Interrupt descriptor header and patch interrupt descriptor.
+  //     5 bytes for interrupt descriptor header, 2 bytes for End Tag
+  //
+  DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);
+  //
+  //   3.1 Patch Length bit[7:0] of Interrupt descirptor patch interrupt descriptor
+  //
+  *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);
+  //
+  //   3.2 Patch Interrupt Table Length
+  //
+  *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof (UINT32));
+  //
+  //   3.3 Copy patched InterruptNumBuffer
+  //
+  CopyMem (DataPtr + 5, IrqBuffer, IrqBuffserSize);
+
+  //
+  // 4. Jump over Interrupt descirptor and Patch END Tag, set Checksum field to 0
+  //
+  DataPtr       += 5 + IrqBuffserSize;
+  *DataPtr       = ACPI_END_TAG_DESCRIPTOR;
+  *(DataPtr + 1) = 0;
+
+  //
+  // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP
+  //
+  DataPtr += 2;
+  if (DataPtr < DataEndPtr) {
+    SetMem (DataPtr, (UINTN)DataEndPtr - (UINTN)DataPtr, AML_NOOP_OP);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize and publish TPM items in ACPI table.
+
+  @retval   EFI_SUCCESS     The TCG ACPI table is published successfully.
+  @retval   Others          The TCG ACPI table is not published.
+
+**/
+EFI_STATUS
+PublishAcpiTable (
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_ACPI_TABLE_PROTOCOL      *AcpiTable;
+  UINTN                        TableKey;
+  EFI_ACPI_DESCRIPTION_HEADER  *Table;
+  UINTN                        TableSize;
+  UINT32                       *PossibleIrqNumBuf;
+  UINT32                       PossibleIrqNumBufSize;
+  BOOLEAN                      IsShortFormPkgLength;
+
+  IsShortFormPkgLength = FALSE;
+
+  Status = GetSectionFromFv (
+             &gEfiCallerIdGuid,
+             EFI_SECTION_RAW,
+             0,
+             (VOID **)&Table,
+             &TableSize
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Update Table version before measuring it to PCR
+  //
+  Status = UpdatePPVersion (Table, (CHAR8 *)PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer));
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((
+    DEBUG_INFO,
+    "Current physical presence interface version - %a\n",
+    (CHAR8 *)PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer)
+    ));
+
+  //
+
+  if (PcdGet32 (PcdTpm2CurrentIrqNum) != 0) {
+    //
+    // Patch _PRS interrupt resource only when TPM interrupt is supported
+    //
+    PossibleIrqNumBuf     = (UINT32 *)PcdGetPtr (PcdTpm2PossibleIrqNumBuf);
+    PossibleIrqNumBufSize = (UINT32)PcdGetSize (PcdTpm2PossibleIrqNumBuf);
+
+    if ((PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE) && ((PossibleIrqNumBufSize % sizeof (UINT32)) == 0)) {
+      Status = UpdatePossibleResource (Table, PossibleIrqNumBuf, PossibleIrqNumBufSize, &IsShortFormPkgLength);
+      DEBUG ((
+        DEBUG_INFO,
+        "UpdatePossibleResource status - %x. TPM2 service may not ready in OS.\n",
+        Status
+        ));
+    } else {
+      DEBUG ((
+        DEBUG_INFO,
+        "PcdTpm2PossibleIrqNumBuf size %x is not correct. TPM2 service may not ready in OS.\n",
+        PossibleIrqNumBufSize
+        ));
+    }
+  }
+
+  //
+  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
+  //
+  TpmMeasureAndLogData (
+    0,
+    EV_POST_CODE,
+    EV_POSTCODE_INFO_ACPI_DATA,
+    ACPI_DATA_LEN,
+    Table,
+    TableSize
+    );
+
+  ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
+  CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId));
+
+  DEBUG ((DEBUG_INFO, "FtpmControlArea: 0x%lX\n", (UINTN)(VOID *)mFtpmControlArea));
+  DEBUG ((DEBUG_INFO, "CommandSize: 0x%lX, ResponseSize: 0x%lX \n", mFtpmControlArea->CommandSize, mFtpmControlArea->ResponseSize));
+
+  Status = AssignMemory32Fixed (Table, (UINT32)mFtpmControlArea->CommandAddress, (UINT32)mFtpmControlArea->ResponseAddress);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = PatchTpmControlAreaOpRegion (Table, SIGNATURE_32 ('T', 'P', 'M', 'C'), (UINT32)(UINTN)(VOID *)mFtpmControlArea + 0x10, sizeof (EFI_TPM2_ACPI_CONTROL_AREA));
+  ASSERT_EFI_ERROR (Status);
+
+  mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16)sizeof (TCG_NVS));
+  ASSERT (mTcgNvs != NULL);
+  mTcgNvs->TpmIrqNum            = PcdGet32 (PcdTpm2CurrentIrqNum);
+  mTcgNvs->IsShortFormPkgLength = IsShortFormPkgLength;
+
+  //
+  // Publish the TPM ACPI table. Table is re-checksumed.
+  //
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
+  ASSERT_EFI_ERROR (Status);
+
+  TableKey = 0;
+  Status   = AcpiTable->InstallAcpiTable (
+                          AcpiTable,
+                          Table,
+                          TableSize,
+                          &TableKey
+                          );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Publish TPM2 ACPI table
+
+  @retval   EFI_SUCCESS     The TPM2 ACPI table is published successfully.
+  @retval   Others          The TPM2 ACPI table is not published.
+
+**/
+EFI_STATUS
+PublishTpm2 (
+  VOID
+  )
+{
+  EFI_STATUS               Status;
+  EFI_ACPI_TABLE_PROTOCOL  *AcpiTable;
+  UINTN                    TableKey;
+  UINT64                   OemTableId;
+
+  mTpm2AcpiTemplate.Header.Revision = PcdGet8 (PcdTpm2AcpiTableRev);
+  DEBUG ((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate.Header.Revision));
+
+  //
+  // PlatformClass is only valid for version 4 and above
+  //    BIT0~15:  PlatformClass
+  //    BIT16~31: Reserved
+  //
+  if (mTpm2AcpiTemplate.Header.Revision >= EFI_TPM2_ACPI_TABLE_REVISION_4) {
+    mTpm2AcpiTemplate.Flags = (mTpm2AcpiTemplate.Flags & 0xFFFF0000) | PcdGet8 (PcdTpmPlatformClass);
+    DEBUG ((DEBUG_INFO, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate.Flags & 0x0000FFFF)));
+  }
+
+  //
+  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
+  //
+  TpmMeasureAndLogData (
+    0,
+    EV_POST_CODE,
+    EV_POSTCODE_INFO_ACPI_DATA,
+    ACPI_DATA_LEN,
+    &mTpm2AcpiTemplate,
+    sizeof (mTpm2AcpiTemplate)
+    );
+
+  mTpm2AcpiTemplate.StartMethod          = EFI_TPM2_ACPI_TABLE_START_METHOD_ACPI;
+  mTpm2AcpiTemplate.AddressOfControlArea = ((UINT64)(UINTN)(VOID *)mFtpmControlArea + 0x10);
+
+  CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));
+  OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+  CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
+  mTpm2AcpiTemplate.Header.OemRevision     = PcdGet32 (PcdAcpiDefaultOemRevision);
+  mTpm2AcpiTemplate.Header.CreatorId       = PcdGet32 (PcdAcpiDefaultCreatorId);
+  mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+  //
+  // Construct ACPI table
+  //
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = AcpiTable->InstallAcpiTable (
+                        AcpiTable,
+                        &mTpm2AcpiTemplate,
+                        sizeof (mTpm2AcpiTemplate),
+                        &TableKey
+                        );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  The driver's entry point.
+
+  It install callbacks for TPM physical presence and MemoryClear, and locate
+  SMM variable to be used in the callback function.
+
+  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
+  @param[in] SystemTable  A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS     The entry point is executed successfully.
+  @retval Others          Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeTcgSmm (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                     Status;
+  EFI_SMM_SW_DISPATCH2_PROTOCOL  *SwDispatch;
+  EFI_SMM_SW_REGISTER_CONTEXT    SwContext;
+  EFI_HANDLE                     SwHandle;
+
+  DEBUG ((DEBUG_INFO, "InitializeTcgSmm Entry \n"));
+  if (!CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)) {
+    DEBUG ((DEBUG_ERROR, "No TPM2 DTPM instance required!\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  // if (!GetFtpmControlArea(&mFtpmControlArea)) {
+  //   DEBUG ((DEBUG_ERROR, "Get fTPM Control Area failed!\n"));
+  //   return EFI_UNSUPPORTED;
+  // }
+  mFtpmControlArea = (VOID *)(UINTN)PcdGet64 (PcdTpmBaseAddress);
+  DEBUG ((DEBUG_INFO, "Get PcdTpmBaseAddress:%x\n", mFtpmControlArea));
+  Status = PublishAcpiTable ();
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Get the Sw dispatch protocol and register SMI callback functions.
+  //
+  Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID **)&SwDispatch);
+  ASSERT_EFI_ERROR (Status);
+  SwContext.SwSmiInputValue = (UINTN)-1;
+  Status                    = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8)SwContext.SwSmiInputValue;
+  DEBUG ((DEBUG_INFO, "PhysicalPresence SoftwareSmi: 0x%X\n", (UINT8)SwContext.SwSmiInputValue));
+
+  SwContext.SwSmiInputValue = (UINTN)-1;
+  Status                    = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);
+  ASSERT_EFI_ERROR (Status);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  mTcgNvs->MemoryClear.SoftwareSmi = (UINT8)SwContext.SwSmiInputValue;
+  DEBUG ((DEBUG_INFO, "MemoryClear SoftwareSmi: 0x%X\n", (UINT8)SwContext.SwSmiInputValue));
+
+  //
+  // Locate SmmVariableProtocol.
+  //
+  Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Set TPM2 ACPI table
+  //
+  Status = PublishTpm2 ();
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h
new file mode 100644
index 0000000000..0e9b367c80
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.h
@@ -0,0 +1,123 @@
+/** @file
+  The header file for Tcg2 SMM driver.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef TCG2_SMM_H_
+#define TCG2_SMM_H_
+
+#include <PiDxe.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Tpm2Acpi.h>
+
+#include <Guid/MemoryOverwriteControl.h>
+#include <Guid/TpmInstance.h>
+
+#include <Protocol/SmmSwDispatch2.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/SmmVariable.h>
+#include <Protocol/Tcg2Protocol.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/TpmMeasurementLib.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+#include <Library/IoLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PcdLib.h>
+#include <Library/AmdPspCommonLib.h>
+#include <Library/AmdPspFtpmLib.h>
+#include <IndustryStandard/TpmPtp.h>
+
+#pragma pack(1)
+typedef struct {
+  UINT8     SoftwareSmi;
+  UINT32    Parameter;
+  UINT32    Response;
+  UINT32    Request;
+  UINT32    RequestParameter;
+  UINT32    LastRequest;
+  UINT32    ReturnCode;
+} PHYSICAL_PRESENCE_NVS;
+
+typedef struct {
+  UINT8     SoftwareSmi;
+  UINT32    Parameter;
+  UINT32    Request;
+  UINT32    ReturnCode;
+} MEMORY_CLEAR_NVS;
+
+typedef struct {
+  PHYSICAL_PRESENCE_NVS    PhysicalPresence;
+  MEMORY_CLEAR_NVS         MemoryClear;
+  UINT32                   PPRequestUserConfirm;
+  UINT32                   TpmIrqNum;
+  BOOLEAN                  IsShortFormPkgLength;
+} TCG_NVS;
+
+typedef struct {
+  UINT8     OpRegionOp;
+  UINT32    NameString;
+  UINT8     RegionSpace;
+  UINT8     DWordPrefix;
+  UINT32    RegionOffset;
+  UINT8     BytePrefix;
+  UINT8     RegionLen;
+} AML_OP_REGION_32_8;
+#pragma pack()
+
+//
+// The definition for TCG MOR
+//
+#define ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE  1
+#define ACPI_FUNCTION_PTS_CLEAR_MOR_BIT           2
+
+//
+// The return code for Memory Clear Interface Functions
+//
+#define MOR_REQUEST_SUCCESS          0
+#define MOR_REQUEST_GENERAL_FAILURE  1
+
+//
+// Physical Presence Interface Version supported by Platform
+//
+#define PHYSICAL_PRESENCE_VERSION_TAG   "$PV"
+#define PHYSICAL_PRESENCE_VERSION_SIZE  4
+
+//
+// PNP _HID for TPM2 device
+//
+#define TPM_HID_TAG        "NNNN0000"
+#define TPM_HID_PNP_SIZE   8
+#define TPM_HID_ACPI_SIZE  9
+
+#define TPM_PRS_RESL           "RESL"
+#define TPM_PRS_RESS           "RESS"
+#define TPM_PRS_RES_NAME_SIZE  4
+//
+// Minimum PRS resource template size
+//  1 byte    for  BufferOp
+//  1 byte    for  PkgLength
+//  2 bytes   for  BufferSize
+//  12 bytes  for  Memory32Fixed descriptor
+//  5 bytes   for  Interrupt descriptor
+//  2 bytes   for  END Tag
+//
+#define TPM_POS_RES_TEMPLATE_MIN_SIZE  (1 + 1 + 2 + 12 + 5 + 2)
+
+//
+// Max Interrupt buffer size for PRS interrupt resource
+// Now support 15 interrupts in maxmum
+//
+#define MAX_PRS_INT_BUF_SIZE  (15*4)
+#endif // TCG_SMM_H_
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf
new file mode 100644
index 0000000000..52419f55ea
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.inf
@@ -0,0 +1,92 @@
+## @file
+#  Provides ACPI methods for fTPM 2.0 support
+#
+#  Spec Compliance Info:
+#     "TCG ACPI Specification Level 00 Revision 00.37"
+#     "Physical Presence Interface Specification Version 1.30 Revision 00.52"
+#     "Platform Reset Attack Mitigation Specification Version 1.00"
+#    TPM2.0 ACPI device object
+#     "TCG PC Client Platform Firmware Profile Specification for TPM Family 2.0 Level 00 Revision 00.21"
+#
+#  This driver implements TPM 2.0 definition block in ACPI table and
+#  registers SMI callback functions for Tcg2 physical presence and
+#  MemoryClear to handle the requests from ACPI method.
+#
+#  Caution: This module requires additional review when modified.
+#  This driver will have external input - variable and ACPINvs data in SMM mode.
+#  This external input must be validated carefully to avoid security issue.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tcg2Smm
+  MODULE_UNI_FILE                = Tcg2Smm.uni
+  FILE_GUID                      = 44A20657-10B8-4049-A148-ACD8812AF257
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  PI_SPECIFICATION_VERSION       = 0x0001000A
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializeTcgSmm
+
+[Sources]
+  Tcg2Smm.h
+  Tcg2Smm.c
+  Tpm.asl
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  UefiDriverEntryPoint
+  SmmServicesTableLib
+  UefiBootServicesTableLib
+  DebugLib
+  DxeServicesLib
+  TpmMeasurementLib
+  Tcg2PhysicalPresenceLib
+  PcdLib
+  # AmdPspCommonLib
+
+[Guids]
+  ## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControl"
+  ## SOMETIMES_CONSUMES ## Variable:L"MemoryOverwriteRequestControl"
+  gEfiMemoryOverwriteControlDataGuid
+  gEfiTpmDeviceInstanceTpm20DtpmGuid                            ## CONSUMES           ## GUID       # TPM device identifier
+
+[Protocols]
+  gEfiSmmSwDispatch2ProtocolGuid                                ## CONSUMES
+  gEfiSmmVariableProtocolGuid                                   ## CONSUMES
+  gEfiAcpiTableProtocolGuid                                     ## CONSUMES
+
+[Pcd]
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid              ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId            ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId       ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision      ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId        ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision  ## SOMETIMES_CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer  ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev                 ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass                 ## SOMETIMES_CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2CurrentIrqNum            ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf        ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress
+
+[Depex]
+  gEfiAcpiTableProtocolGuid AND
+  gEfiSmmSwDispatch2ProtocolGuid AND
+  gEfiSmmVariableProtocolGuid AND
+  gEfiTcg2ProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  Tcg2SmmExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni
new file mode 100644
index 0000000000..d2cf9159c6
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni
@@ -0,0 +1,19 @@
+// /** @file
+// Provides ACPI metholds for fTPM 2.0 support
+//
+// This driver implements TPM 2.0 definition block in ACPI table and
+// registers SMI callback functions for TCG2 physical presence and
+// MemoryClear to handle the requests from ACPI method.
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "Provides ACPI metholds for TPM 2.0 support"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This driver implements TPM 2.0 definition block in ACPI table and registers SMI callback functions for TCG2 physical presence and MemoryClear to handle the requests from ACPI method.\n"
+                                                        "Caution: This module requires additional review when modified. This driver will have external input - variable and ACPINvs data in SMM mode. This external input must be validated carefully to avoid security issues."
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni
new file mode 100644
index 0000000000..b85ec10eba
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2SmmExtra.uni
@@ -0,0 +1,15 @@
+// /** @file
+// Tcg2Smm Localized Strings and Content
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"TCG2 (Trusted Computing Group) SMM"
+
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl
new file mode 100644
index 0000000000..a11ce43f85
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl
@@ -0,0 +1,397 @@
+/** @file
+  The TPM2 definition block in ACPI table for TCG2 physical presence
+  and MemoryClear.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+(c)Copyright 2016 HP Development Company, L.P.<BR>
+Copyright (c) 2017, Microsoft Corporation.  All rights reserved. <BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DefinitionBlock (
+  "Tpm.aml",
+  "SSDT",
+  2,
+  "AMD   ",
+  "Tpm2Tabl",
+  0x1000
+  )
+{
+  Scope (\_SB)
+  {
+    Device (TPM)
+    {
+      //
+      // TCG2
+      //
+
+      //
+      //  TAG for patching TPM2.0 _HID
+      //
+      Name (_HID, "MSFT0101")
+
+      Name (_CID, "MSFT0101")
+
+      //
+      // Readable name of this device, don't know if this way is correct yet
+      //
+      Name (_STR, Unicode ("TPM 2.0 Device"))
+
+      //
+      // Return the resource consumed by TPM device
+      //
+      Name (_CRS, ResourceTemplate () {
+        Memory32Fixed (ReadWrite, 0xA5A5A5A5, 0x4000)  // Command Address
+        Memory32Fixed (ReadWrite, 0xAAAAAAAA, 0x4000)  // Response Address
+      })
+
+      //
+      // Operational region for Smi port access, FixedPcdGet16 (PcdAmdFchCfgSmiCmdPortAddr)
+      //
+      OperationRegion (SMIP, SystemIO, 0xB0, 1)
+      Field (SMIP, ByteAcc, NoLock, Preserve)
+      {
+          IOB0, 8
+      }
+
+      //
+      // Operational region for fTPM control area.
+      // Region Offset 0xFFFF0000 and Length 0xF0 will be fixed in C code.
+      //
+      OperationRegion (TPMC, SystemMemory, 0xFFFF0000, 0xF0)
+      Field (TPMC, DWordAcc, NoLock, Preserve)
+      {
+        REQS,   32,
+        STAS,   32,
+        CANC,   32,
+        STAR,   32,
+                AccessAs (QWordAcc, 0),
+        INTC,   64,
+                AccessAs (DWordAcc, 0),
+        CMDS,   32,
+                AccessAs (QWordAcc, 0),
+        CMDA,   64,
+                AccessAs (DWordAcc, 0),
+        RSPS,   32,
+                AccessAs (QWordAcc, 0),
+        RSPA,   64
+      }
+
+      //
+      // Operational region for TPM support, TPM Physical Presence and TPM Memory Clear
+      // Region Offset 0xFFFF0000 and Length 0xF0 will be fixed in C code.
+      //
+      OperationRegion (TNVS, SystemMemory, 0xFFFF0000, 0xF0)
+      Field (TNVS, AnyAcc, NoLock, Preserve)
+      {
+        PPIN,   8,  //   Software SMI for Physical Presence Interface
+        PPIP,   32, //   Used for save physical presence paramter
+        PPRP,   32, //   Physical Presence request operation response
+        PPRQ,   32, //   Physical Presence request operation
+        PPRM,   32, //   Physical Presence request operation parameter
+        LPPR,   32, //   Last Physical Presence request operation
+        FRET,   32, //   Physical Presence function return code
+        MCIN,   8,  //   Software SMI for Memory Clear Interface
+        MCIP,   32, //   Used for save the Mor paramter
+        MORD,   32, //   Memory Overwrite Request Data
+        MRET,   32, //   Memory Overwrite function return code
+        UCRQ,   32  //   Phyical Presence request operation to Get User Confirmation Status
+      }
+
+      Method (PTS, 1, Serialized)
+      {
+        //
+        // Detect Sx state for MOR, only S4, S5 need to handle
+        //
+        If (LAnd (LLess (Arg0, 6), LGreater (Arg0, 3)))
+        {
+          //
+          // Bit4 -- DisableAutoDetect. 0 -- Firmware MAY autodetect.
+          //
+          If (LNot (And (MORD, 0x10)))
+          {
+            //
+            // Trigger the SMI through ACPI _PTS method.
+            //
+            Store (0x02, MCIP)
+
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (MCIN, IOB0)
+          }
+        }
+        Return (0)
+      }
+
+      Method (_STA, 0)
+      {
+        Return (0x0f)
+      }
+
+      //
+      // TCG Hardware Information
+      //
+      Method (HINF, 3, Serialized, 0, {BuffObj, PkgObj}, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj
+      {
+        //
+        // Switch by function index
+        //
+        Switch (ToInteger(Arg1))
+        {
+          Case (0)
+          {
+            //
+            // Standard query
+            //
+            Return (Buffer () {0x03})
+          }
+          Case (1)
+          {
+            //
+            // Return failure if no TPM present
+            //
+            Name(TPMV, Package () {0x01, Package () {0x2, 0x0}})
+            if (LEqual (_STA (), 0x00))
+            {
+              Return (Package () {0x00})
+            }
+
+            //
+            // Return TPM version
+            //
+            Return (TPMV)
+          }
+          Default {BreakPoint}
+        }
+        Return (Buffer () {0})
+      }
+
+      Name(TPM2, Package (0x02){
+        Zero,
+        Zero
+      })
+
+      Name(TPM3, Package (0x03){
+        Zero,
+        Zero,
+        Zero
+      })
+
+      //
+      // TCG Physical Presence Interface
+      //
+      Method (TPPI, 3, Serialized, 0, {BuffObj, PkgObj, IntObj, StrObj}, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj
+      {
+        //
+        // Switch by function index
+        //
+        Switch (ToInteger(Arg1))
+        {
+          Case (0)
+          {
+            //
+            // Standard query, supports function 1-8
+            //
+            Return (Buffer () {0xFF, 0x01})
+          }
+          Case (1)
+          {
+            //
+            // a) Get Physical Presence Interface Version
+            //
+            Return ("$PV")
+          }
+          Case (2)
+          {
+            //
+            // b) Submit TPM Operation Request to Pre-OS Environment
+            //
+            Store (DerefOf (Index (Arg2, 0x00)), PPRQ)
+            Store (0, PPRM)
+            Store (0x02, PPIP)
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (PPIN, IOB0)
+            Return (FRET)
+
+
+          }
+          Case (3)
+          {
+            //
+            // c) Get Pending TPM Operation Requested By the OS
+            //
+            Store (PPRQ, Index (TPM2, 0x01))
+            Return (TPM2)
+          }
+          Case (4)
+          {
+            //
+            // d) Get Platform-Specific Action to Transition to Pre-OS Environment
+            //
+            Return (2)
+          }
+          Case (5)
+          {
+            //
+            // e) Return TPM Operation Response to OS Environment
+            //
+            Store (0x05, PPIP)
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (PPIN, IOB0)
+            Store (LPPR, Index (TPM3, 0x01))
+            Store (PPRP, Index (TPM3, 0x02))
+
+            Return (TPM3)
+          }
+          Case (6)
+          {
+
+            //
+            // f) Submit preferred user language (Not implemented)
+            //
+
+            Return (3)
+
+          }
+          Case (7)
+          {
+            //
+            // g) Submit TPM Operation Request to Pre-OS Environment 2
+            //
+            Store (7, PPIP)
+            Store (DerefOf (Index (Arg2, 0x00)), PPRQ)
+            Store (0, PPRM)
+            If (LEqual (PPRQ, 23)) {
+              Store (DerefOf (Index (Arg2, 0x01)), PPRM)
+            }
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (PPIN, IOB0)
+            Return (FRET)
+          }
+          Case (8)
+          {
+            //
+            // e) Get User Confirmation Status for Operation
+            //
+            Store (8, PPIP)
+            Store (DerefOf (Index (Arg2, 0x00)), UCRQ)
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (PPIN, IOB0)
+            Return (FRET)
+          }
+
+          Default {BreakPoint}
+        }
+        Return (1)
+      }
+
+      Method (TMCI, 3, Serialized, 0, IntObj, {UnknownObj, UnknownObj, UnknownObj}) // IntObj, IntObj, PkgObj
+      {
+        //
+        // Switch by function index
+        //
+        Switch (ToInteger (Arg1))
+        {
+          Case (0)
+          {
+            //
+            // Standard query, supports function 1-1
+            //
+            Return (Buffer () {0x03})
+          }
+          Case (1)
+          {
+            //
+            // Save the Operation Value of the Request to MORD (reserved memory)
+            //
+            Store (DerefOf (Index (Arg2, 0x00)), MORD)
+            //
+            // Trigger the SMI through ACPI _DSM method.
+            //
+            Store (0x01, MCIP)
+            //
+            // Trigger the SMI interrupt
+            //
+            Store (MCIN, IOB0)
+            Return (MRET)
+          }
+          Default {BreakPoint}
+        }
+        Return (1)
+      }
+
+      // ACPI Start Method to permit the OS to request the firmware to execute or cancel a TPM 2.0 command.
+      Method (TPMS, 3, Serialized, 0, {BuffObj, PkgObj, IntObj, StrObj}, {UnknownObj, UnknownObj, UnknownObj})
+      {
+        //
+        // Switch by function index
+        //
+        Switch (ToInteger(Arg1)) {
+
+        Case (0) {
+          //
+          // Standard query, supports function 1
+          //
+          Return (Buffer () {0x03})
+        }
+
+        Case (1) {
+          //
+          // Start
+          //
+          Return (0)
+        }
+
+        Default {BreakPoint}
+        }
+        Return (1)
+      }
+
+      Method (_DSM, 4, Serialized, 0, UnknownObj, {BuffObj, IntObj, IntObj, PkgObj})
+      {
+        //
+        // TCG Hardware Information
+        //
+        If(LEqual(Arg0, ToUUID ("cf8e16a5-c1e8-4e25-b712-4f54a96702c8")))
+        {
+          Return (HINF (Arg1, Arg2, Arg3))
+        }
+        //
+        // TCG Physical Presence Interface
+        //
+        If(LEqual(Arg0, ToUUID ("3dddfaa6-361b-4eb4-a424-8d10089d1653")))
+        {
+          Return (TPPI (Arg1, Arg2, Arg3))
+        }
+        //
+        // TCG Memory Clear Interface
+        //
+        If(LEqual(Arg0, ToUUID ("376054ed-cc13-4675-901c-4756d7f2d45d")))
+        {
+          Return (TMCI (Arg1, Arg2, Arg3))
+        }
+        //
+        // ACPI Start Method
+        //
+        If(LEqual (Arg0, ToUUID ("6bbf6cab-5463-4714-b7cd-f0203c0368d4")))
+        {
+          Return (TPMS (Arg1, Arg2, Arg3))
+        }
+
+        Return (Buffer () {0})
+      }
+    }
+  }
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
new file mode 100644
index 0000000000..8833c40f74
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
@@ -0,0 +1,124 @@
+/** @file
+  Header file for NV data structure definition.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef TCG2_CONFIG_NV_DATA_H_
+#define TCG2_CONFIG_NV_DATA_H_
+
+#include <Guid/HiiPlatformSetupFormset.h>
+#include <Guid/Tcg2ConfigHii.h>
+#include <IndustryStandard/TcgPhysicalPresence.h>
+
+//
+// BUGBUG: In order to pass VfrCompiler, we have to redefine below MACRO, which already in <Protocol/Tcg2Protocol.h>.
+//
+#ifndef TCG2_H_
+#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2  0x00000001
+#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2    0x00000002
+#endif
+#define EFI_TCG2_EVENT_LOG_FORMAT_ALL  (EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
+
+#define TCG2_CONFIGURATION_VARSTORE_ID       0x0001
+#define TCG2_CONFIGURATION_INFO_VARSTORE_ID  0x0002
+#define TCG2_VERSION_VARSTORE_ID             0x0003
+#define TCG2_CONFIGURATION_FORM_ID           0x0001
+
+#define KEY_TPM_DEVICE                0x2000
+#define KEY_TPM2_OPERATION            0x2001
+#define KEY_TPM2_OPERATION_PARAMETER  0x2002
+#define KEY_TPM2_PCR_BANKS_REQUEST_0  0x2003
+#define KEY_TPM2_PCR_BANKS_REQUEST_1  0x2004
+#define KEY_TPM2_PCR_BANKS_REQUEST_2  0x2005
+#define KEY_TPM2_PCR_BANKS_REQUEST_3  0x2006
+#define KEY_TPM2_PCR_BANKS_REQUEST_4  0x2007
+#define KEY_TPM_DEVICE_INTERFACE      0x2008
+#define KEY_TCG2_PPI_VERSION          0x2009
+#define KEY_TPM2_ACPI_REVISION        0x200A
+
+#define TPM_DEVICE_NULL      0
+#define TPM_DEVICE_1_2       1
+#define TPM_DEVICE_2_0_DTPM  2
+#define TPM_DEVICE_MIN       TPM_DEVICE_1_2
+#define TPM_DEVICE_MAX       TPM_DEVICE_2_0_DTPM
+#define TPM_DEVICE_DEFAULT   TPM_DEVICE_2_0_DTPM
+
+#define TPM2_ACPI_REVISION_3  3
+#define TPM2_ACPI_REVISION_4  4
+
+#define TPM_DEVICE_INTERFACE_TIS       0
+#define TPM_DEVICE_INTERFACE_PTP_FIFO  1
+#define TPM_DEVICE_INTERFACE_PTP_CRB   2
+#define TPM_DEVICE_INTERFACE_MAX       TPM_DEVICE_INTERFACE_PTP_FIFO
+#define TPM_DEVICE_INTERFACE_DEFAULT   TPM_DEVICE_INTERFACE_PTP_CRB
+
+#define TCG2_PROTOCOL_VERSION_DEFAULT      0x0001
+#define EFI_TCG2_EVENT_LOG_FORMAT_DEFAULT  EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
+
+#define TCG2_PPI_VERSION_1_2  0x322E31                    // "1.2"
+#define TCG2_PPI_VERSION_1_3  0x332E31                    // "1.3"
+
+//
+// Nv Data structure referenced by IFR, TPM device user desired
+//
+typedef struct {
+  UINT8    TpmDevice;
+} TCG2_CONFIGURATION;
+
+typedef struct {
+  UINT64    PpiVersion;
+  UINT8     Tpm2AcpiTableRev;
+} TCG2_VERSION;
+
+typedef struct {
+  BOOLEAN    Sha1Supported;
+  BOOLEAN    Sha256Supported;
+  BOOLEAN    Sha384Supported;
+  BOOLEAN    Sha512Supported;
+  BOOLEAN    Sm3Supported;
+  UINT8      TpmDeviceInterfaceAttempt;
+  BOOLEAN    TpmDeviceInterfacePtpFifoSupported;
+  BOOLEAN    TpmDeviceInterfacePtpCrbSupported;
+} TCG2_CONFIGURATION_INFO;
+
+//
+// Variable saved for S3, TPM detected, only valid in S3 path.
+// This variable is ReadOnly.
+//
+typedef struct {
+  UINT8    TpmDeviceDetected;
+} TCG2_DEVICE_DETECTION;
+
+#define TCG2_STORAGE_NAME           L"TCG2_CONFIGURATION"
+#define TCG2_STORAGE_INFO_NAME      L"TCG2_CONFIGURATION_INFO"
+#define TCG2_DEVICE_DETECTION_NAME  L"TCG2_DEVICE_DETECTION"
+#define TCG2_VERSION_NAME           L"TCG2_VERSION"
+
+#define TPM_INSTANCE_ID_LIST  { \
+  {TPM_DEVICE_INTERFACE_NONE,           TPM_DEVICE_NULL},      \
+  {TPM_DEVICE_INTERFACE_TPM12,          TPM_DEVICE_1_2},       \
+  {TPM_DEVICE_INTERFACE_TPM20_DTPM,     TPM_DEVICE_2_0_DTPM},  \
+}
+
+//
+// BUGBUG: In order to pass VfrCompiler, we have to redefine GUID here.
+//
+#ifndef __BASE_H__
+typedef struct {
+  UINT32    Data1;
+  UINT16    Data2;
+  UINT16    Data3;
+  UINT8     Data4[8];
+} GUID;
+#endif
+
+typedef struct {
+  GUID     TpmInstanceGuid;
+  UINT8    TpmDevice;
+} TPM_INSTANCE_ID;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
new file mode 100644
index 0000000000..e1530fb874
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
@@ -0,0 +1,77 @@
+## @file
+#  Set TPM device type
+#
+#  This module initializes TPM device type based on variable and detection.
+#  NOTE: This module is only for reference only, each platform should have its own setup page.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Tcg2ConfigPei
+  MODULE_UNI_FILE                = Tcg2ConfigPei.uni
+  FILE_GUID                      = EADD5061-93EF-4CCC-8450-F78A7F0820F0
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = Tcg2ConfigPeimEntryPoint
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+# [BootMode]
+#   S3_RESUME                 ## SOMETIMES_CONSUMES
+#
+
+[Sources]
+  Tcg2ConfigPeim.c
+  Tcg2ConfigNvData.h
+  TpmDetection.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  PeiServicesLib
+  PeimEntryPoint
+  DebugLib
+  PcdLib
+  Tpm2CommandLib
+  Tpm2DeviceLib
+  IoLib
+  PciExpressLib
+
+[Guids]
+  ## SOMETIMES_CONSUMES ## Variable:L"TCG2_CONFIGURATION"
+  ## SOMETIMES_CONSUMES ## Variable:L"TCG2_DEVICE_DETECTION"
+  gTcg2ConfigFormSetGuid
+  gEfiTpmDeviceSelectedGuid           ## PRODUCES             ## GUID    # Used as a PPI GUID
+  gEfiTpmDeviceInstanceNoneGuid       ## SOMETIMES_CONSUMES   ## GUID    # TPM device identifier
+
+[Ppis]
+  gEfiPeiReadOnlyVariable2PpiGuid     ## CONSUMES
+  gPeiTpmInitializationDonePpiGuid    ## SOMETIMES_PRODUCES
+
+[Pcd]
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid                 ## PRODUCES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInitializationPolicy         ## PRODUCES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmAutoDetection                ## CONSUMES
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress                  ## SOMETIMES_CONSUMES
+  gPlatformPkgTokenSpaceGuid.PcdSpiDtpmEnabled
+
+[Depex]
+  gEfiPeiMemoryDiscoveredPpiGuid AND
+  gEfiPeiMasterBootModePpiGuid AND
+  gEfiPeiReadOnlyVariable2PpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  Tcg2ConfigPeiExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni
new file mode 100644
index 0000000000..4d1e7ae6ac
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPei.uni
@@ -0,0 +1,14 @@
+// /** @file
+// Set TPM device type
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#string STR_MODULE_ABSTRACT             #language en-US "Set TPM device type"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This module initializes TPM device type based on variable and detection.\n"
+                                                        "NOTE: This module is only for reference only, each platform should have its own setup page."
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni
new file mode 100644
index 0000000000..0e79ee614a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeiExtra.uni
@@ -0,0 +1,15 @@
+// /** @file
+// Tcg2ConfigDxe Localized Strings and Content
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"TCG2 (Trusted Computing Group) Configuration DXE"
+
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
new file mode 100644
index 0000000000..9d90581388
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
@@ -0,0 +1,148 @@
+/** @file
+  The module entry point for Tcg2 configuration module.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Guid/TpmInstance.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/TpmInitialized.h>
+#include <Protocol/Tcg2Protocol.h>
+#include "Tcg2ConfigNvData.h"
+
+TPM_INSTANCE_ID  mTpmInstanceId[] = TPM_INSTANCE_ID_LIST;
+
+CONST EFI_PEI_PPI_DESCRIPTOR  gTpmSelectedPpi = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiTpmDeviceSelectedGuid,
+  NULL
+};
+
+EFI_PEI_PPI_DESCRIPTOR  mTpmInitializationDonePpiList = {
+  EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+  &gPeiTpmInitializationDonePpiGuid,
+  NULL
+};
+
+/**
+  This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration.
+
+  @param  SetupTpmDevice  TpmDevice configuration in setup driver
+
+  @return TpmDevice configuration
+**/
+UINT8
+DetectTpmDevice (
+  IN UINT8  SetupTpmDevice
+  );
+
+/**
+  The entry point for Tcg2 configuration driver.
+
+  @param  FileHandle  Handle of the file being invoked.
+  @param  PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCES             Convert variable to PCD successfully.
+  @retval Others                 Fail to convert variable to PCD.
+**/
+EFI_STATUS
+EFIAPI
+Tcg2ConfigPeimEntryPoint (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  UINTN                            Size;
+  EFI_STATUS                       Status;
+  EFI_STATUS                       Status2;
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *VariablePpi;
+  TCG2_CONFIGURATION               Tcg2Configuration;
+  UINTN                            Index;
+  UINT8                            TpmDevice;
+
+  Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **)&VariablePpi);
+  ASSERT_EFI_ERROR (Status);
+
+  Size   = sizeof (Tcg2Configuration);
+  Status = VariablePpi->GetVariable (
+                          VariablePpi,
+                          TCG2_STORAGE_NAME,
+                          &gTcg2ConfigFormSetGuid,
+                          NULL,
+                          &Size,
+                          &Tcg2Configuration
+                          );
+  if (EFI_ERROR (Status)) {
+    //
+    // Variable not ready, set default value
+    //
+    Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT;
+  }
+
+  //
+  // Validation
+  //
+  if ((Tcg2Configuration.TpmDevice > TPM_DEVICE_MAX) || (Tcg2Configuration.TpmDevice < TPM_DEVICE_MIN)) {
+    Tcg2Configuration.TpmDevice = TPM_DEVICE_DEFAULT;
+  }
+
+  //
+  // Although we have SetupVariable info, we still need detect TPM device manually.
+  //
+  DEBUG ((DEBUG_INFO, "Tcg2Configuration.TpmDevice from Setup: %x\n", Tcg2Configuration.TpmDevice));
+
+  if (PcdGetBool (PcdTpmAutoDetection)) {
+    TpmDevice = DetectTpmDevice (Tcg2Configuration.TpmDevice);
+    DEBUG ((DEBUG_INFO, "TpmDevice final: %x\n", TpmDevice));
+    if (TpmDevice != TPM_DEVICE_NULL) {
+      Tcg2Configuration.TpmDevice = TpmDevice;
+    }
+  } else {
+    TpmDevice = Tcg2Configuration.TpmDevice;
+  }
+
+  //
+  // Convert variable to PCD.
+  // This is work-around because there is no gurantee DynamicHiiPcd can return correct value in DXE phase.
+  // Using DynamicPcd instead.
+  //
+  // NOTE: Tcg2Configuration variable contains the desired TpmDevice type,
+  // while PcdTpmInstanceGuid PCD contains the real detected TpmDevice type
+  //
+  for (Index = 0; Index < sizeof (mTpmInstanceId)/sizeof (mTpmInstanceId[0]); Index++) {
+    if (TpmDevice == mTpmInstanceId[Index].TpmDevice) {
+      Size   = sizeof (mTpmInstanceId[Index].TpmInstanceGuid);
+      Status = PcdSetPtrS (PcdTpmInstanceGuid, &Size, &mTpmInstanceId[Index].TpmInstanceGuid);
+      ASSERT_EFI_ERROR (Status);
+      DEBUG ((DEBUG_INFO, "TpmDevice PCD: %g\n", &mTpmInstanceId[Index].TpmInstanceGuid));
+      break;
+    }
+  }
+
+  //
+  // Selection done
+  //
+  Status = PeiServicesInstallPpi (&gTpmSelectedPpi);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Even if no TPM is selected or detected, we still need intall TpmInitializationDonePpi.
+  // Because TcgPei or Tcg2Pei will not run, but we still need a way to notify other driver.
+  // Other driver can know TPM initialization state by TpmInitializedPpi.
+  //
+  if (CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid)) {
+    Status2 = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
+    ASSERT_EFI_ERROR (Status2);
+  }
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c
new file mode 100644
index 0000000000..4a31738b13
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/Tcg2Config/TpmDetection.c
@@ -0,0 +1,99 @@
+/** @file
+  fTPM2.0/dTPM2.0 auto detection.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/IoLib.h>
+#include <IndustryStandard/Tpm20.h>
+#include "Tcg2ConfigNvData.h"
+
+EFI_STATUS
+InitDtpmInterface (
+  IN  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine check both SetupVariable and real TPM device, and return final TpmDevice configuration.
+
+  @param  SetupTpmDevice  TpmDevice configuration in setup driver
+
+  @return TpmDevice configuration
+**/
+UINT8
+DetectTpmDevice (
+  IN UINT8  SetupTpmDevice
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_BOOT_MODE                    BootMode;
+  TCG2_DEVICE_DETECTION            Tcg2DeviceDetection;
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *VariablePpi;
+  UINTN                            Size;
+
+  Status = PeiServicesGetBootMode (&BootMode);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // In S3, we rely on normal boot Detection, because we save to ReadOnly Variable in normal boot.
+  //
+  if (BootMode == BOOT_ON_S3_RESUME) {
+    DEBUG ((DEBUG_INFO, "DetectTpmDevice: S3 mode\n"));
+
+    Status = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **)&VariablePpi);
+    ASSERT_EFI_ERROR (Status);
+
+    Size = sizeof (TCG2_DEVICE_DETECTION);
+    ZeroMem (&Tcg2DeviceDetection, sizeof (Tcg2DeviceDetection));
+    Status = VariablePpi->GetVariable (
+                            VariablePpi,
+                            TCG2_DEVICE_DETECTION_NAME,
+                            &gTcg2ConfigFormSetGuid,
+                            NULL,
+                            &Size,
+                            &Tcg2DeviceDetection
+                            );
+    if (!EFI_ERROR (Status) &&
+        (Tcg2DeviceDetection.TpmDeviceDetected >= TPM_DEVICE_MIN) &&
+        (Tcg2DeviceDetection.TpmDeviceDetected <= TPM_DEVICE_MAX))
+    {
+      DEBUG ((DEBUG_INFO, "TpmDevice from DeviceDetection: %x\n", Tcg2DeviceDetection.TpmDeviceDetected));
+      Status = Tpm2Startup (TPM_SU_STATE);
+      return Tcg2DeviceDetection.TpmDeviceDetected;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "DetectTpmDevice:\n"));
+
+  Status = Tpm2RequestUseTpm ();
+  if (EFI_ERROR (Status)) {
+    //
+    // TPM 2.0 not available
+    //
+    return TPM_DEVICE_NULL;
+  }
+
+  Status = Tpm2Startup (TPM_SU_CLEAR);
+  DEBUG ((DEBUG_INFO, "Tpm2Startup: %r\n", Status));
+  if (EFI_ERROR (Status)) {
+    return TPM_DEVICE_NULL;
+  }
+
+  return TPM_DEVICE_2_0_DTPM;
+}
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114596): https://edk2.groups.io/g/devel/message/114596
Mute This Topic: https://groups.io/mt/103975473/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 21/32] AMD/VanGoghBoard: Check in SignedCapsule
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (19 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 20/32] AMD/VanGoghBoard: Check in FTPM module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 22/32] AMD/VanGoghBoard: Check in Vtf0 Zhai, MingXin (Duke) via groups.io
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial SignedCapsule module for Signed Capsule.
  Produce FMP instance to update system firmware.

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>
---
 .../BaseTools/Source/Python/GenFds/Capsule.py |  253 +++
 .../SystemFirmwareUpdate/ParseConfigProfile.c |  217 +++
 .../SystemFirmwareCommonDxe.c                 |  371 +++++
 .../SystemFirmwareUpdate/SystemFirmwareDxe.h  |  421 +++++
 .../SystemFirmwareUpdateDxe.c                 | 1426 +++++++++++++++++
 .../SystemFirmwareUpdateDxe.inf               |   77 +
 .../SystemFirmwareUpdateDxe.uni               |   15 +
 .../SystemFirmwareUpdateDxeExtra.uni          |   15 +
 8 files changed, 2795 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFds/Capsule.py
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFds/Capsule.py b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFds/Capsule.py
new file mode 100644
index 0000000000..0ec0b3ca43
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFds/Capsule.py
@@ -0,0 +1,253 @@
+## @file
+# generate capsule
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc.
+#  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import absolute_import
+from .GenFdsGlobalVariable import GenFdsGlobalVariable, FindExtendTool
+from CommonDataClass.FdfClass import CapsuleClassObject
+import Common.LongFilePathOs as os
+from io import BytesIO
+from Common.Misc import SaveFileOnChange, PackGUID
+import uuid
+from struct import pack
+from Common import EdkLogger
+from Common.BuildToolError import GENFDS_ERROR
+from Common.DataType import TAB_LINE_BREAK
+
+WIN_CERT_REVISION = 0x0200
+WIN_CERT_TYPE_EFI_GUID = 0x0EF1
+EFI_CERT_TYPE_PKCS7_GUID = uuid.UUID('{4aafd29d-68df-49ee-8aa9-347d375665a7}')
+EFI_CERT_TYPE_RSA2048_SHA256_GUID = uuid.UUID('{a7717414-c616-4977-9420-844712a735bf}')
+
+## create inf file describes what goes into capsule and call GenFv to generate capsule
+#
+#
+class Capsule (CapsuleClassObject):
+    ## The constructor
+    #
+    #   @param  self        The object pointer
+    #
+    def __init__(self):
+        CapsuleClassObject.__init__(self)
+        # For GenFv
+        self.BlockSize = None
+        # For GenFv
+        self.BlockNum = None
+        self.CapsuleName = None
+
+    ## Generate FMP capsule
+    #
+    #   @retval string      Generated Capsule file path
+    #
+    def GenFmpCapsule(self):
+        #
+        # Generate capsule header
+        # typedef struct {
+        #     EFI_GUID          CapsuleGuid;
+        #     UINT32            HeaderSize;
+        #     UINT32            Flags;
+        #     UINT32            CapsuleImageSize;
+        # } EFI_CAPSULE_HEADER;
+        #
+        Header = BytesIO()
+        #
+        # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A
+        #
+        Header.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split('-')))
+        HdrSize = 0
+        if 'CAPSULE_HEADER_SIZE' in self.TokensDict:
+            Header.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)))
+            HdrSize = int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16)
+        else:
+            Header.write(pack('=I', 0x20))
+            HdrSize = 0x20
+        Flags = 0
+        if 'CAPSULE_FLAGS' in self.TokensDict:
+            for flag in self.TokensDict['CAPSULE_FLAGS'].split(','):
+                flag = flag.strip()
+                if flag == 'PopulateSystemTable':
+                    Flags |= 0x00010000 | 0x00020000
+                elif flag == 'PersistAcrossReset':
+                    Flags |= 0x00010000
+                elif flag == 'InitiateReset':
+                    Flags |= 0x00040000
+        if 'OEM_CAPSULE_FLAGS' in self.TokensDict:
+            Flags |= int(self.TokensDict['OEM_CAPSULE_FLAGS'],16)
+        Header.write(pack('=I', Flags))
+        #
+        # typedef struct {
+        #     UINT32 Version;
+        #     UINT16 EmbeddedDriverCount;
+        #     UINT16 PayloadItemCount;
+        #     // UINT64 ItemOffsetList[];
+        # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER;
+        #
+        FwMgrHdr = BytesIO()
+        if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict:
+            FwMgrHdr.write(pack('=I', int(self.TokensDict['CAPSULE_HEADER_INIT_VERSION'], 16)))
+        else:
+            FwMgrHdr.write(pack('=I', 0x00000001))
+        FwMgrHdr.write(pack('=HH', len(self.CapsuleDataList), len(self.FmpPayloadList)))
+        FwMgrHdrSize = 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPayloadList))
+
+        #
+        # typedef struct _WIN_CERTIFICATE {
+        #   UINT32 dwLength;
+        #   UINT16 wRevision;
+        #   UINT16 wCertificateType;
+        # //UINT8 bCertificate[ANYSIZE_ARRAY];
+        # } WIN_CERTIFICATE;
+        #
+        # typedef struct _WIN_CERTIFICATE_UEFI_GUID {
+        #   WIN_CERTIFICATE Hdr;
+        #   EFI_GUID        CertType;
+        # //UINT8 CertData[ANYSIZE_ARRAY];
+        # } WIN_CERTIFICATE_UEFI_GUID;
+        #
+        # typedef struct {
+        #   UINT64                    MonotonicCount;
+        #   WIN_CERTIFICATE_UEFI_GUID AuthInfo;
+        # } EFI_FIRMWARE_IMAGE_AUTHENTICATION;
+        #
+        # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 {
+        #   EFI_GUID HashType;
+        #   UINT8 PublicKey[256];
+        #   UINT8 Signature[256];
+        # } EFI_CERT_BLOCK_RSA_2048_SHA256;
+        #
+
+        PreSize = FwMgrHdrSize
+        Content = BytesIO()
+        for driver in self.CapsuleDataList:
+            FileName = driver.GenCapsuleSubItem()
+            FwMgrHdr.write(pack('=Q', PreSize))
+            PreSize += os.path.getsize(FileName)
+            File = open(FileName, 'rb')
+            Content.write(File.read())
+            File.close()
+        for fmp in self.FmpPayloadList:
+            if fmp.Existed:
+                FwMgrHdr.write(pack('=Q', PreSize))
+                PreSize += len(fmp.Buffer)
+                Content.write(fmp.Buffer)
+                continue
+            if fmp.ImageFile:
+                for Obj in fmp.ImageFile:
+                    fmp.ImageFile = Obj.GenCapsuleSubItem()
+            if fmp.VendorCodeFile:
+                for Obj in fmp.VendorCodeFile:
+                    fmp.VendorCodeFile = Obj.GenCapsuleSubItem()
+            if fmp.Certificate_Guid:
+                ExternalTool, ExternalOption = FindExtendTool([], GenFdsGlobalVariable.ArchList, fmp.Certificate_Guid)
+                CmdOption = ''
+                CapInputFile = fmp.ImageFile
+                if not os.path.isabs(fmp.ImageFile):
+                    CapInputFile = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, fmp.ImageFile)
+                CapOutputTmp = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.tmp'
+                if ExternalTool is None:
+                    EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % fmp.Certificate_Guid)
+                else:
+                    CmdOption += ExternalTool
+                if ExternalOption:
+                    CmdOption = CmdOption + ' ' + ExternalOption
+                CmdOption += ' -e ' + ' --monotonic-count ' + str(fmp.MonotonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile
+                CmdList = CmdOption.split()
+                GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to generate FMP auth capsule")
+                if uuid.UUID(fmp.Certificate_Guid) == EFI_CERT_TYPE_PKCS7_GUID:
+                    dwLength = 4 + 2 + 2 + 16 + os.path.getsize(CapOutputTmp) - os.path.getsize(CapInputFile)
+                else:
+                    dwLength = 4 + 2 + 2 + 16 + 16 + 256 + 256
+                fmp.ImageFile = CapOutputTmp
+                AuthData = [fmp.MonotonicCount, dwLength, WIN_CERT_REVISION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid]
+                fmp.Buffer = fmp.GenCapsuleSubItem(AuthData)
+            else:
+                fmp.Buffer = fmp.GenCapsuleSubItem()
+            FwMgrHdr.write(pack('=Q', PreSize))
+            PreSize += len(fmp.Buffer)
+            Content.write(fmp.Buffer)
+        BodySize = len(FwMgrHdr.getvalue()) + len(Content.getvalue())
+        Header.write(pack('=I', HdrSize + BodySize))
+        #
+        # The real capsule header structure is 28 bytes
+        #
+        Header.write(b'\x00'*(HdrSize-28))
+        Header.write(FwMgrHdr.getvalue())
+        Header.write(Content.getvalue())
+        #
+        # Generate FMP capsule file
+        #
+        CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName) + '.Cap'
+        SaveFileOnChange(CapOutputFile, Header.getvalue(), True)
+        return CapOutputFile
+
+    ## Generate capsule
+    #
+    #   @param  self        The object pointer
+    #   @retval string      Generated Capsule file path
+    #
+    def GenCapsule(self):
+        if self.UiCapsuleName.upper() + 'cap' in GenFdsGlobalVariable.ImageBinDict:
+            return GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap']
+
+        GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCapsuleName)
+        if ('CAPSULE_GUID' in self.TokensDict and
+            uuid.UUID(self.TokensDict['CAPSULE_GUID']) == uuid.UUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A')):
+            return self.GenFmpCapsule()
+
+        CapInfFile = self.GenCapInf()
+        CapInfFile.append("[files]" + TAB_LINE_BREAK)
+        CapFileList = []
+        for CapsuleDataObj in self.CapsuleDataList:
+            CapsuleDataObj.CapsuleName = self.CapsuleName
+            FileName = CapsuleDataObj.GenCapsuleSubItem()
+            CapsuleDataObj.CapsuleName = None
+            CapFileList.append(FileName)
+            CapInfFile.append("EFI_FILE_NAME = " + \
+                                   FileName      + \
+                                   TAB_LINE_BREAK)
+        SaveFileOnChange(self.CapInfFileName, ''.join(CapInfFile), False)
+        #
+        # Call GenFv tool to generate capsule
+        #
+        CapOutputFile = os.path.join(GenFdsGlobalVariable.FvDir, self.UiCapsuleName)
+        CapOutputFile = CapOutputFile + '.Cap'
+        GenFdsGlobalVariable.GenerateFirmwareVolume(
+                                CapOutputFile,
+                                [self.CapInfFileName],
+                                Capsule=True,
+                                FfsList=CapFileList
+                                )
+
+        GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Successfully" %self.UiCapsuleName)
+        GenFdsGlobalVariable.SharpCounter = 0
+        GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'cap'] = CapOutputFile
+        return CapOutputFile
+
+    ## Generate inf file for capsule
+    #
+    #   @param  self        The object pointer
+    #   @retval file        inf file object
+    #
+    def GenCapInf(self):
+        self.CapInfFileName = os.path.join(GenFdsGlobalVariable.FvDir,
+                                   self.UiCapsuleName +  "_Cap" + '.inf')
+        CapInfFile = []
+
+        CapInfFile.append("[options]" + TAB_LINE_BREAK)
+
+        for Item in self.TokensDict:
+            CapInfFile.append("EFI_"                    + \
+                                  Item                      + \
+                                  ' = '                     + \
+                                  self.TokensDict[Item]     + \
+                                  TAB_LINE_BREAK)
+
+        return CapInfFile
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c
new file mode 100644
index 0000000000..bfd4e876f3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c
@@ -0,0 +1,217 @@
+/** @file
+  Implements ParseConfigProfile.c
+  Parse the INI configuration file and pass the information to the update driver
+  so that the driver can perform update accordingly.
+  
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SystemFirmwareDxe.h"
+#include <Library/IniParsingLib.h>
+#include <Library/PrintLib.h>
+
+#define MAX_LINE_LENGTH  512
+
+/**
+  Parse Config data file to get the updated data array.
+
+  @param[in]      DataBuffer      Config raw file buffer.
+  @param[in]      BufferSize      Size of raw buffer.
+  @param[in, out] ConfigHeader    Pointer to the config header.
+  @param[in, out] UpdateArray     Pointer to the config of update data.
+
+  @retval EFI_NOT_FOUND         No config data is found.
+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
+  @retval EFI_SUCCESS           Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseUpdateDataFile (
+  IN      UINT8               *DataBuffer,
+  IN      UINTN               BufferSize,
+  IN OUT  CONFIG_HEADER       *ConfigHeader,
+  IN OUT  UPDATE_CONFIG_DATA  **UpdateArray
+  )
+{
+  EFI_STATUS  Status;
+  CHAR8       *SectionName;
+  CHAR8       Entry[MAX_LINE_LENGTH];
+  UINTN       Num;
+  UINT64      Num64;
+  UINTN       Index;
+  EFI_GUID    FileGuid;
+  VOID        *Context;
+
+  //
+  // First process the data buffer and get all sections and entries
+  //
+  Context = OpenIniFile (DataBuffer, BufferSize);
+  if (Context == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Now get NumOfUpdate
+  //
+  Status = GetDecimalUintnFromDataFile (
+             Context,
+             "Head",
+             "NumOfUpdate",
+             &Num
+             );
+  if (EFI_ERROR (Status) || (Num == 0)) {
+    DEBUG ((DEBUG_ERROR, "NumOfUpdate not found\n"));
+    CloseIniFile (Context);
+    return EFI_NOT_FOUND;
+  }
+
+  ConfigHeader->NumOfUpdates = Num;
+  *UpdateArray               = AllocateZeroPool ((sizeof (UPDATE_CONFIG_DATA) * Num));
+  if (*UpdateArray == NULL) {
+    CloseIniFile (Context);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for (Index = 0; Index < ConfigHeader->NumOfUpdates; Index++) {
+    //
+    // Get the section name of each update
+    //
+    AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update");
+    AsciiValueToStringS (
+      Entry + AsciiStrnLenS (Entry, MAX_LINE_LENGTH),
+      MAX_LINE_LENGTH - AsciiStrnLenS (Entry, MAX_LINE_LENGTH),
+      0,
+      Index,
+      0
+      );
+    Status = GetStringFromDataFile (
+               Context,
+               "Head",
+               Entry,
+               &SectionName
+               );
+    if (EFI_ERROR (Status) || (SectionName == NULL)) {
+      DEBUG ((DEBUG_ERROR, "[%d] %a not found\n", Index, Entry));
+      CloseIniFile (Context);
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // The section name of this update has been found.
+    // Now looks for all the config data of this update
+    //
+    (*UpdateArray)[Index].Index = Index;
+
+    //
+    // FirmwareType
+    //
+    Status = GetDecimalUintnFromDataFile (
+               Context,
+               SectionName,
+               "FirmwareType",
+               &Num
+               );
+    if (EFI_ERROR (Status)) {
+      CloseIniFile (Context);
+      DEBUG ((DEBUG_ERROR, "[%d] FirmwareType not found\n", Index));
+      return EFI_NOT_FOUND;
+    }
+
+    (*UpdateArray)[Index].FirmwareType = (PLATFORM_FIRMWARE_TYPE)Num;
+
+    //
+    // AddressType
+    //
+    Status = GetDecimalUintnFromDataFile (
+               Context,
+               SectionName,
+               "AddressType",
+               &Num
+               );
+    if (EFI_ERROR (Status)) {
+      CloseIniFile (Context);
+      DEBUG ((DEBUG_ERROR, "[%d] AddressType not found\n", Index));
+      return EFI_NOT_FOUND;
+    }
+
+    (*UpdateArray)[Index].AddressType = (FLASH_ADDRESS_TYPE)Num;
+
+    //
+    // BaseAddress
+    //
+    Status = GetHexUint64FromDataFile (
+               Context,
+               SectionName,
+               "BaseAddress",
+               &Num64
+               );
+    if (EFI_ERROR (Status)) {
+      CloseIniFile (Context);
+      DEBUG ((DEBUG_ERROR, "[%d] BaseAddress not found\n", Index));
+      return EFI_NOT_FOUND;
+    }
+
+    (*UpdateArray)[Index].BaseAddress = (EFI_PHYSICAL_ADDRESS)Num64;
+
+    //
+    // FileBuid
+    //
+    Status = GetGuidFromDataFile (
+               Context,
+               SectionName,
+               "FileGuid",
+               &FileGuid
+               );
+    if (EFI_ERROR (Status)) {
+      CloseIniFile (Context);
+      DEBUG ((DEBUG_ERROR, "[%d] FileGuid not found\n", Index));
+      return EFI_NOT_FOUND;
+    }
+
+    CopyGuid (&((*UpdateArray)[Index].FileGuid), &FileGuid);
+
+    //
+    // Length
+    //
+    Status = GetHexUintnFromDataFile (
+               Context,
+               SectionName,
+               "Length",
+               &Num
+               );
+    if (EFI_ERROR (Status)) {
+      CloseIniFile (Context);
+      DEBUG ((DEBUG_ERROR, "[%d] Length not found\n", Index));
+      return EFI_NOT_FOUND;
+    }
+
+    (*UpdateArray)[Index].Length = (UINTN)Num;
+
+    //
+    // ImageOffset
+    //
+    Status = GetHexUintnFromDataFile (
+               Context,
+               SectionName,
+               "ImageOffset",
+               &Num
+               );
+    if (EFI_ERROR (Status)) {
+      CloseIniFile (Context);
+      DEBUG ((DEBUG_ERROR, "[%d] ImageOffset not found\n", Index));
+      return EFI_NOT_FOUND;
+    }
+
+    (*UpdateArray)[Index].ImageOffset = (UINTN)Num;
+  }
+
+  //
+  // Now all configuration data got. Free those temporary buffers
+  //
+  CloseIniFile (Context);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
new file mode 100644
index 0000000000..05a36162d3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
@@ -0,0 +1,371 @@
+/** @file
+  Produce FMP instance for system firmware.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SystemFirmwareDxe.h"
+
+EFI_GUID  gSystemFmpLastAttemptVariableGuid = SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID;
+EFI_GUID  gSystemFmpProtocolGuid            = SYSTEM_FMP_PROTOCOL_GUID;
+
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL  mFirmwareManagementProtocol = {
+  FmpGetImageInfo,
+  FmpGetImage,
+  FmpSetImage,
+  FmpCheckImage,
+  FmpGetPackageInfo,
+  FmpSetPackageInfo
+};
+
+/**
+  Returns information about the current firmware image(s) of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
+                                     On input, this is the size of the buffer allocated by the caller.
+                                     On output, it is the size of the buffer returned by the firmware
+                                     if the buffer was large enough, or the size of the buffer needed
+                                     to contain the image(s) information if the buffer was too small.
+  @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
+                                     information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
+                                     associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
+                                     descriptors or firmware images within this device.
+  @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
+                                     of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
+                                     The format is vendor specific and new version must have a greater value
+                                     than the old version. If PackageVersion is not supported, the value is
+                                     0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+                                     is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+                                     that package version update is in progress.
+  @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
+                                     package version name. The buffer is allocated by this function with
+                                     AllocatePool(), and it is the caller's responsibility to free it with a call
+                                     to FreePool().
+
+  @retval EFI_SUCCESS                The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
+                                     needed to hold the image(s) information is returned in ImageInfoSize.
+  @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
+  @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo (
+  IN        EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN OUT    UINTN                             *ImageInfoSize,
+  IN OUT    EFI_FIRMWARE_IMAGE_DESCRIPTOR     *ImageInfo,
+  OUT       UINT32                            *DescriptorVersion,
+  OUT       UINT8                             *DescriptorCount,
+  OUT       UINTN                             *DescriptorSize,
+  OUT       UINT32                            *PackageVersion,
+  OUT       CHAR16                            **PackageVersionName
+  )
+{
+  SYSTEM_FMP_PRIVATE_DATA                 *SystemFmpPrivate;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR  *ImageDescriptor;
+
+  SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP (This);
+
+  if (ImageInfoSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (*ImageInfoSize < sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpPrivate->DescriptorCount) {
+    *ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpPrivate->DescriptorCount;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if ((ImageInfo == NULL) ||
+      (DescriptorVersion == NULL) ||
+      (DescriptorCount == NULL) ||
+      (DescriptorSize == NULL) ||
+      (PackageVersion == NULL) ||
+      (PackageVersionName == NULL))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *ImageInfoSize     = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpPrivate->DescriptorCount;
+  *DescriptorSize    = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
+  *DescriptorCount   = SystemFmpPrivate->DescriptorCount;
+  *DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+
+  //
+  // supports 1 ImageInfo descriptor
+  //
+  ImageDescriptor       = SystemFmpPrivate->ImageDescriptor;
+  ImageInfo->ImageIndex = ImageDescriptor->ImageIndex;
+  CopyGuid (&ImageInfo->ImageTypeId, &ImageDescriptor->ImageTypeId);
+  ImageInfo->ImageId = ImageDescriptor->ImageId;
+  if (ImageDescriptor->ImageIdNameStringOffset != 0) {
+    ImageInfo->ImageIdName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->ImageIdNameStringOffset);
+  } else {
+    ImageInfo->ImageIdName = NULL;
+  }
+
+  ImageInfo->Version = ImageDescriptor->Version;
+  if (ImageDescriptor->VersionNameStringOffset != 0) {
+    ImageInfo->VersionName = (CHAR16 *)((UINTN)ImageDescriptor + ImageDescriptor->VersionNameStringOffset);
+  } else {
+    ImageInfo->VersionName = NULL;
+  }
+
+  ImageInfo->Size                        = (UINTN)ImageDescriptor->Size;
+  ImageInfo->AttributesSupported         = ImageDescriptor->AttributesSupported;
+  ImageInfo->AttributesSetting           = ImageDescriptor->AttributesSetting;
+  ImageInfo->Compatibilities             = ImageDescriptor->Compatibilities;
+  ImageInfo->LowestSupportedImageVersion = ImageDescriptor->LowestSupportedImageVersion;
+  ImageInfo->LastAttemptVersion          = SystemFmpPrivate->LastAttempt.LastAttemptVersion;
+  ImageInfo->LastAttemptStatus           = SystemFmpPrivate->LastAttempt.LastAttemptStatus;
+  ImageInfo->HardwareInstance            = ImageDescriptor->HardwareInstance;
+
+  //
+  // package version
+  //
+  *PackageVersion = ImageDescriptor->PackageVersion;
+  if (ImageDescriptor->PackageVersionNameStringOffset != 0) {
+    *PackageVersionName = (VOID *)((UINTN)ImageDescriptor + ImageDescriptor->PackageVersionNameStringOffset);
+    *PackageVersionName = AllocateCopyPool (StrSize (*PackageVersionName), *PackageVersionName);
+  } else {
+    *PackageVersionName = NULL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieves a copy of the current firmware image of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]     This            A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]     ImageIndex      A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in,out] Image           Points to the buffer where the current image is copied to.
+  @param[in,out] ImageSize       On entry, points to the size of the buffer pointed to by Image, in bytes.
+                                 On return, points to the length of the image, in bytes.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
+                                 image. The current buffer size needed to hold the image is returned
+                                 in ImageSize.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  OUT  VOID                         *Image,
+  IN  OUT  UINTN                        *ImageSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Checks if the firmware image is valid for the device.
+
+  This function allows firmware update application to validate the firmware image without
+  invoking the SetImage() first.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
+                                 if available, additional information if the image is invalid.
+
+  @retval EFI_SUCCESS            The image was successfully checked.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  OUT UINT32                            *ImageUpdatable
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Returns information about the firmware package.
+
+  This function returns package information.
+
+  @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[out] PackageVersion           A version number that represents all the firmware images in the device.
+                                       The format is vendor specific and new version must have a greater value
+                                       than the old version. If PackageVersion is not supported, the value is
+                                       0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+                                       comparison is to be performed using PackageVersionName. A value of
+                                       0xFFFFFFFD indicates that package version update is in progress.
+  @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
+                                       the package version name. The buffer is allocated by this function with
+                                       AllocatePool(), and it is the caller's responsibility to free it with a
+                                       call to FreePool().
+  @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+                                       package version name. A value of 0 indicates the device does not support
+                                       update of package version name. Length is the number of Unicode characters,
+                                       including the terminating null character.
+  @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
+                                       Definitions' for possible returned values of this parameter. A value of 1
+                                       indicates the attribute is supported and the current setting value is
+                                       indicated in AttributesSetting. A value of 0 indicates the attribute is not
+                                       supported and the current setting value in AttributesSetting is meaningless.
+  @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
+                                       values of this parameter
+
+  @retval EFI_SUCCESS                  The package information was successfully returned.
+  @retval EFI_UNSUPPORTED              The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  OUT UINT32                            *PackageVersion,
+  OUT CHAR16                            **PackageVersionName,
+  OUT UINT32                            *PackageVersionNameMaxLen,
+  OUT UINT64                            *AttributesSupported,
+  OUT UINT64                            *AttributesSetting
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Updates information about the firmware package.
+
+  This function updates package information.
+  This function returns EFI_UNSUPPORTED if the package information is not updatable.
+  VendorCode enables vendor to implement vendor-specific package information update policy.
+  Null if the caller did not specify this policy or use the default policy.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  Image              Points to the authentication image.
+                                 Null if authentication is not required.
+  @param[in]  ImageSize          Size of the authentication image in bytes.
+                                 0 if authentication is not required.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
+                                 image update policy.
+                                 Null indicates the caller did not specify this policy or use
+                                 the default policy.
+  @param[in]  PackageVersion     The new package version.
+  @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
+                                 the package version name.
+                                 The string length is equal to or less than the value returned in
+                                 PackageVersionNameMaxLen.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new package
+                                 information.
+  @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
+                                 returned in PackageVersionNameMaxLen.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  IN  CONST VOID                        *VendorCode,
+  IN  UINT32                            PackageVersion,
+  IN  CONST CHAR16                      *PackageVersionName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Initialize SystemFmpDriver private data structure.
+
+  @param[in] SystemFmpPrivate  private data structure to be initialized.
+
+  @return EFI_SUCCESS private data is initialized.
+**/
+EFI_STATUS
+InitializePrivateData (
+  IN SYSTEM_FMP_PRIVATE_DATA  *SystemFmpPrivate
+  )
+{
+  EFI_STATUS  VarStatus;
+  UINTN       VarSize;
+
+  SystemFmpPrivate->Signature       = SYSTEM_FMP_PRIVATE_DATA_SIGNATURE;
+  SystemFmpPrivate->Handle          = NULL;
+  SystemFmpPrivate->DescriptorCount = 1;
+  CopyMem (&SystemFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
+
+  SystemFmpPrivate->ImageDescriptor = PcdGetPtr (PcdEdkiiSystemFirmwareImageDescriptor);
+
+  SystemFmpPrivate->LastAttempt.LastAttemptVersion = 0x0;
+  SystemFmpPrivate->LastAttempt.LastAttemptStatus  = 0x0;
+  VarSize                                          = sizeof (SystemFmpPrivate->LastAttempt);
+  VarStatus                                        = gRT->GetVariable (
+                                                            SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+                                                            &gSystemFmpLastAttemptVariableGuid,
+                                                            NULL,
+                                                            &VarSize,
+                                                            &SystemFmpPrivate->LastAttempt
+                                                            );
+  DEBUG ((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus));
+  DEBUG ((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.
+
+  @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR
+
+  @retval TRUE  It is a system FMP.
+  @retval FALSE It is a device FMP.
+**/
+BOOLEAN
+IsSystemFmp (
+  IN EFI_FIRMWARE_IMAGE_DESCRIPTOR  *FmpImageInfo
+  )
+{
+  GUID   *Guid;
+  UINTN  Count;
+  UINTN  Index;
+
+  Guid  = PcdGetPtr (PcdSystemFmpCapsuleImageTypeIdGuid);
+  Count = PcdGetSize (PcdSystemFmpCapsuleImageTypeIdGuid) / sizeof (GUID);
+
+  for (Index = 0; Index < Count; Index++, Guid++) {
+    if (CompareGuid (&FmpImageInfo->ImageTypeId, Guid)) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h
new file mode 100644
index 0000000000..431d725914
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h
@@ -0,0 +1,421 @@
+/** @file
+  System Firmware update header file.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SYSTEM_FIRMWARE_UPDATE_H_
+#define SYSTEM_FIRMWARE_UPDATE_H_
+
+#include <PiDxe.h>
+
+#include <Guid/SystemResourceTable.h>
+#include <Guid/FirmwareContentsSigned.h>
+#include <Guid/WinCertificate.h>
+#include <Guid/EdkiiSystemFmpCapsule.h>
+
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/EdkiiSystemCapsuleLib.h>
+#include <Library/AmdPspBaseLibV2.h>
+#include <OtaCapsuleUpdate.h>
+
+typedef struct {
+  UINT32    LastAttemptVersion;
+  UINT32    LastAttemptStatus;
+} SYSTEM_FMP_LAST_ATTEMPT_VARIABLE;
+
+#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME  L"SystemLastAttempVar"
+
+#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID  {0x2f564d6f, 0xcc2c, 0x4838, { 0xb9, 0xa8, 0xbe, 0x59, 0x48, 0xb0, 0x3d, 0x59 }}
+
+#define SYSTEM_FMP_PRIVATE_DATA_SIGNATURE  SIGNATURE_32('S', 'Y', 'S', 'F')
+
+#define SYSTEM_FMP_PROTOCOL_GUID  {0x6d16624a, 0x26a6, 0x4cb4, { 0x84, 0xfa, 0x6, 0x78, 0x5a, 0x7e, 0x82, 0x6a }}
+
+//
+// SYSTEM FMP private data structure.
+//
+
+struct _SYSTEM_FMP_PRIVATE_DATA {
+  UINT32                                    Signature;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL          Fmp;
+  EFI_HANDLE                                Handle;
+  UINT8                                     DescriptorCount;
+  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR    *ImageDescriptor;
+  SYSTEM_FMP_LAST_ATTEMPT_VARIABLE          LastAttempt;
+};
+
+typedef struct _SYSTEM_FMP_PRIVATE_DATA SYSTEM_FMP_PRIVATE_DATA;
+
+/**
+  Returns a pointer to the SYSTEM_FMP_PRIVATE_DATA structure from the input a as Fmp.
+
+  If the signatures matches, then a pointer to the data structure that contains
+  a specified field of that data structure is returned.
+
+  @param  a              Pointer to the field specified by ServiceBinding within
+                         a data structure of type SYSTEM_FMP_PRIVATE_DATA.
+
+**/
+#define SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(a) \
+  CR ( \
+  (a), \
+  SYSTEM_FMP_PRIVATE_DATA, \
+  Fmp, \
+  SYSTEM_FMP_PRIVATE_DATA_SIGNATURE \
+  )
+
+//
+// Update data
+//
+
+typedef struct {
+  UINTN    NumOfUpdates;
+} CONFIG_HEADER;
+
+typedef struct {
+  UINTN                     Index;
+  PLATFORM_FIRMWARE_TYPE    FirmwareType;
+  FLASH_ADDRESS_TYPE        AddressType;
+  EFI_GUID                  FileGuid;
+  EFI_PHYSICAL_ADDRESS      BaseAddress;
+  UINTN                     Length;
+  UINTN                     ImageOffset;
+} UPDATE_CONFIG_DATA;
+
+//
+// System Firmware Update SMM Communication
+//
+
+#define SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_FUNCTION_SET_IMAGE  1
+
+typedef struct {
+  UINTN         Function;
+  EFI_STATUS    ReturnStatus;
+  // UINT8       Data[];
+} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_HEAD;
+
+#define  ABORT_REASON_MAX_SIZE  0x40              // UnicodeStringSize including final L'\0'
+
+#define  CAPSULE_IMAGE_ADDITIONAL_MAX_SIZE  (0x20020 + 0xA0000) // Addtional size for Capsule Header, FV block alignment + DispatchImage.
+
+typedef struct {
+  UINT8     ImageIndex;
+  UINTN     ImageSize;
+  UINTN     AbortReasonSize;
+  UINT32    LastAttemptVersion;
+  UINT32    LastAttemptStatus;
+  // UINT8       Data[AbortReasonMaxSize + ImageSize];
+} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_SET_IMAGE;
+
+/*
+Name                Offset(byte)    Size(byte)  Comments
+SlotA_Priority      0x0             4           Read and Write the Slot A priority
+SlotA_UpdateRetries 0x4             4           Read and Write the Slot A retries
+SlotA_GlitchRetries 0x8             4           Read only, Slot A glitch
+SlotB_Priority      0xC             4           Read and Write the Slot B priority
+SlotB_UpdateRetries 0x10            4           Read and Write the Slot B retries
+SlotB_GlitchRetries 0x14            4           Read only, Slot B glitch
+
+*/
+typedef struct {
+  UINT32    SlotA_Priority;
+  UINT32    SlotA_UpdateRetries;
+  UINT32    SlotA_GlitchRetries;
+  UINT32    SlotB_Priority;
+  UINT32    SlotB_UpdateRetries;
+  UINT32    SlotB_GlitchRetries;
+} IMAGE_SLOT_HEADER_INFO;
+
+/**
+  Returns information about the current firmware image(s) of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]      This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in, out] ImageInfoSize      A pointer to the size, in bytes, of the ImageInfo buffer.
+                                     On input, this is the size of the buffer allocated by the caller.
+                                     On output, it is the size of the buffer returned by the firmware
+                                     if the buffer was large enough, or the size of the buffer needed
+                                     to contain the image(s) information if the buffer was too small.
+  @param[in, out] ImageInfo          A pointer to the buffer in which firmware places the current image(s)
+                                     information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  @param[out]     DescriptorVersion  A pointer to the location in which firmware returns the version number
+                                     associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     DescriptorCount    A pointer to the location in which firmware returns the number of
+                                     descriptors or firmware images within this device.
+  @param[out]     DescriptorSize     A pointer to the location in which firmware returns the size, in bytes,
+                                     of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out]     PackageVersion     A version number that represents all the firmware images in the device.
+                                     The format is vendor specific and new version must have a greater value
+                                     than the old version. If PackageVersion is not supported, the value is
+                                     0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+                                     is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+                                     that package version update is in progress.
+  @param[out]     PackageVersionName A pointer to a pointer to a null-terminated string representing the
+                                     package version name. The buffer is allocated by this function with
+                                     AllocatePool(), and it is the caller's responsibility to free it with a call
+                                     to FreePool().
+
+  @retval EFI_SUCCESS                The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL       The ImageInfo buffer was too small. The current buffer size
+                                     needed to hold the image(s) information is returned in ImageInfoSize.
+  @retval EFI_INVALID_PARAMETER      ImageInfoSize is NULL.
+  @retval EFI_DEVICE_ERROR           Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImageInfo (
+  IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL      *This,
+  IN OUT    UINTN                          *ImageInfoSize,
+  IN OUT    EFI_FIRMWARE_IMAGE_DESCRIPTOR  *ImageInfo,
+  OUT       UINT32                         *DescriptorVersion,
+  OUT       UINT8                          *DescriptorCount,
+  OUT       UINTN                          *DescriptorSize,
+  OUT       UINT32                         *PackageVersion,
+  OUT       CHAR16                         **PackageVersionName
+  );
+
+/**
+  Retrieves a copy of the current firmware image of the device.
+
+  This function allows a copy of the current firmware image to be created and saved.
+  The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+  @param[in]     This            A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]     ImageIndex      A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in,out] Image           Points to the buffer where the current image is copied to.
+  @param[in,out] ImageSize       On entry, points to the size of the buffer pointed to by Image, in bytes.
+                                 On return, points to the length of the image, in bytes.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_BUFFER_TOO_SMALL   The buffer specified by ImageSize is too small to hold the
+                                 image. The current buffer size needed to hold the image is returned
+                                 in ImageSize.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_NOT_FOUND          The current image is not copied to the buffer.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetImage (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  OUT  VOID                         *Image,
+  IN  OUT  UINTN                        *ImageSize
+  );
+
+/**
+  Updates the firmware image of the device.
+
+  This function updates the hardware with the new firmware image.
+  This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+  If the firmware image is updatable, the function should perform the following minimal validations
+  before proceeding to do the firmware image update.
+  - Validate the image authentication if image has attribute
+    IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+    EFI_SECURITY_VIOLATION if the validation fails.
+  - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+    the image is unsupported. The function can optionally provide more detailed information on
+    why the image is not a supported image.
+  - Validate the data from VendorCode if not null. Image validation must be performed before
+    VendorCode data validation. VendorCode data is ignored or considered invalid if image
+    validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+  VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+  the caller did not specify the policy or use the default policy. As an example, vendor can implement
+  a policy to allow an option to force a firmware image update when the abort reason is due to the new
+  firmware image version is older than the current firmware image version or bad image checksum.
+  Sensitive operations such as those wiping the entire firmware image and render the device to be
+  non-functional should be encoded in the image itself rather than passed with the VendorCode.
+  AbortReason enables vendor to have the option to provide a more detailed description of the abort
+  reason to the caller.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
+                                 Null indicates the caller did not specify the policy or use the default policy.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+  @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
+                                 details for the aborted operation. The buffer is allocated by this function
+                                 with AllocatePool(), and it is the caller's responsibility to free it with a
+                                 call to FreePool().
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_ABORTED            The operation is aborted.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL               *This,
+  IN  UINT8                                          ImageIndex,
+  IN  CONST VOID                                     *Image,
+  IN  UINTN                                          ImageSize,
+  IN  CONST VOID                                     *VendorCode,
+  IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress,
+  OUT CHAR16                                         **AbortReason
+  );
+
+/**
+  Checks if the firmware image is valid for the device.
+
+  This function allows firmware update application to validate the firmware image without
+  invoking the SetImage() first.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[out] ImageUpdatable     Indicates if the new image is valid for update. It also provides,
+                                 if available, additional information if the image is invalid.
+
+  @retval EFI_SUCCESS            The image was successfully checked.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpCheckImage (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  UINT8                             ImageIndex,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  OUT UINT32                            *ImageUpdatable
+  );
+
+/**
+  Returns information about the firmware package.
+
+  This function returns package information.
+
+  @param[in]  This                     A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[out] PackageVersion           A version number that represents all the firmware images in the device.
+                                       The format is vendor specific and new version must have a greater value
+                                       than the old version. If PackageVersion is not supported, the value is
+                                       0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+                                       comparison is to be performed using PackageVersionName. A value of
+                                       0xFFFFFFFD indicates that package version update is in progress.
+  @param[out] PackageVersionName       A pointer to a pointer to a null-terminated string representing
+                                       the package version name. The buffer is allocated by this function with
+                                       AllocatePool(), and it is the caller's responsibility to free it with a
+                                       call to FreePool().
+  @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+                                       package version name. A value of 0 indicates the device does not support
+                                       update of package version name. Length is the number of Unicode characters,
+                                       including the terminating null character.
+  @param[out] AttributesSupported      Package attributes that are supported by this device. See 'Package Attribute
+                                       Definitions' for possible returned values of this parameter. A value of 1
+                                       indicates the attribute is supported and the current setting value is
+                                       indicated in AttributesSetting. A value of 0 indicates the attribute is not
+                                       supported and the current setting value in AttributesSetting is meaningless.
+  @param[out] AttributesSetting        Package attributes. See 'Package Attribute Definitions' for possible returned
+                                       values of this parameter
+
+  @retval EFI_SUCCESS                  The package information was successfully returned.
+  @retval EFI_UNSUPPORTED              The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpGetPackageInfo (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  OUT UINT32                            *PackageVersion,
+  OUT CHAR16                            **PackageVersionName,
+  OUT UINT32                            *PackageVersionNameMaxLen,
+  OUT UINT64                            *AttributesSupported,
+  OUT UINT64                            *AttributesSetting
+  );
+
+/**
+  Updates information about the firmware package.
+
+  This function updates package information.
+  This function returns EFI_UNSUPPORTED if the package information is not updatable.
+  VendorCode enables vendor to implement vendor-specific package information update policy.
+  Null if the caller did not specify this policy or use the default policy.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  Image              Points to the authentication image.
+                                 Null if authentication is not required.
+  @param[in]  ImageSize          Size of the authentication image in bytes.
+                                 0 if authentication is not required.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware
+                                 image update policy.
+                                 Null indicates the caller did not specify this policy or use
+                                 the default policy.
+  @param[in]  PackageVersion     The new package version.
+  @param[in]  PackageVersionName A pointer to the new null-terminated Unicode string representing
+                                 the package version name.
+                                 The string length is equal to or less than the value returned in
+                                 PackageVersionNameMaxLen.
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new package
+                                 information.
+  @retval EFI_INVALID_PARAMETER  The PackageVersionName length is longer than the value
+                                 returned in PackageVersionNameMaxLen.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetPackageInfo (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *This,
+  IN  CONST VOID                        *Image,
+  IN  UINTN                             ImageSize,
+  IN  CONST VOID                        *VendorCode,
+  IN  UINT32                            PackageVersion,
+  IN  CONST CHAR16                      *PackageVersionName
+  );
+
+/**
+  Initialize SystemFmpDriver private data structure.
+
+  @param[in] SystemFmpPrivate  private data structure to be initialized.
+
+  @return EFI_SUCCESS private data is initialized.
+**/
+EFI_STATUS
+InitializePrivateData (
+  IN SYSTEM_FMP_PRIVATE_DATA  *SystemFmpPrivate
+  );
+
+extern EFI_GUID  gSystemFmpLastAttemptVariableGuid;
+extern EFI_GUID  mCurrentImageTypeId;
+extern EFI_GUID  gSystemFmpProtocolGuid;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
new file mode 100644
index 0000000000..894d363de0
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
@@ -0,0 +1,1426 @@
+/** @file
+  SetImage instance to update system firmware.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SystemFirmwareDxe.h"
+
+//
+// SystemFmp driver private data
+//
+SYSTEM_FMP_PRIVATE_DATA  *mSystemFmpPrivate = NULL;
+
+EFI_GUID  mCurrentImageTypeId;
+
+BOOLEAN  mNvRamUpdated = FALSE;
+
+UINT8  mUpdateSlot = 0;
+
+/**
+  Parse Config data file to get the updated data array.
+
+  @param[in]      DataBuffer      Config raw file buffer.
+  @param[in]      BufferSize      Size of raw buffer.
+  @param[in, out] ConfigHeader    Pointer to the config header.
+  @param[in, out] UpdateArray     Pointer to the config of update data.
+
+  @retval EFI_NOT_FOUND         No config data is found.
+  @retval EFI_OUT_OF_RESOURCES  No enough memory is allocated.
+  @retval EFI_SUCCESS           Parse the config file successfully.
+
+**/
+EFI_STATUS
+ParseUpdateDataFile (
+  IN      UINT8               *DataBuffer,
+  IN      UINTN               BufferSize,
+  IN OUT  CONFIG_HEADER       *ConfigHeader,
+  IN OUT  UPDATE_CONFIG_DATA  **UpdateArray
+  );
+
+/**
+  Update System Firmware image component.
+
+  @param[in]  SystemFirmwareImage     Points to the System Firmware image.
+  @param[in]  SystemFirmwareImageSize The length of the System Firmware image in bytes.
+  @param[in]  ConfigData              Points to the component configuration structure.
+  @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[in]  Progress                A function used by the driver to report the progress of the firmware update.
+  @param[in]  StartPercentage         The start completion percentage value that may be used to report progress during the flash write operation.
+  @param[in]  EndPercentage           The end completion percentage value that may be used to report progress during the flash write operation.
+
+  @retval EFI_SUCCESS             The System Firmware image is updated.
+  @retval EFI_WRITE_PROTECTED     The flash device is read only.
+**/
+EFI_STATUS
+PerformUpdate (
+  IN VOID                                           *SystemFirmwareImage,
+  IN UINTN                                          SystemFirmwareImageSize,
+  IN UPDATE_CONFIG_DATA                             *ConfigData,
+  OUT UINT32                                        *LastAttemptVersion,
+  OUT UINT32                                        *LastAttemptStatus,
+  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress,
+  IN UINTN                                          StartPercentage,
+  IN UINTN                                          EndPercentage
+  )
+{
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "PlatformUpdate:"));
+  DEBUG ((DEBUG_INFO, "  BaseAddress - 0x%lx,", ConfigData->BaseAddress));
+  DEBUG ((DEBUG_INFO, "  ImageOffset - 0x%x,", ConfigData->ImageOffset));
+  DEBUG ((DEBUG_INFO, "  Legnth - 0x%x\n", ConfigData->Length));
+  if (Progress != NULL) {
+    Progress (StartPercentage);
+  }
+
+  Status = PerformFlashWriteWithProgress (
+             ConfigData->FirmwareType,
+             ConfigData->BaseAddress,
+             ConfigData->AddressType,
+             (VOID *)((UINTN)SystemFirmwareImage + (UINTN)ConfigData->ImageOffset),
+             ConfigData->Length,
+             Progress,
+             StartPercentage,
+             EndPercentage
+             );
+  if (Progress != NULL) {
+    Progress (EndPercentage);
+  }
+
+  if (!EFI_ERROR (Status)) {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+    if (ConfigData->FirmwareType == PlatformFirmwareTypeNvRam) {
+      mNvRamUpdated = TRUE;
+    }
+  } else {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+  }
+
+  return Status;
+}
+
+/**
+  Get layout of system firmware image.
+
+  @param[in]  SystemFirmwareImage     Points to the System firmware image.
+  @param[out] SlotAOffset             Points to the offste of slot A image.
+  @param[out] SlotBOffset             Points to the offste of slot B image.
+
+  @retval EFI_SUCCESS                 Get system firmware image layout successfully.
+  @retval others                      Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+GetImageLayout (
+  IN VOID     *SystemFirmwareImage,
+  OUT UINT32  *SlotAOffset,
+  OUT UINT32  *SlotBOffset,
+  OUT UINT8   *ActiveSlot
+  )
+{
+  FIRMWARE_ENTRY_TABLEV2  *EfsAddressPtr;
+  PSP_DIRECTORY           *PspL1DirectoryPtr;
+  UINT32                  SlotCount;
+  UINT32                  Index;
+  IMAGE_SLOT_HEADER       *IshSlotAInfoPtr;
+  IMAGE_SLOT_HEADER       *IshSlotBInfoPtr;
+
+  if (SystemFirmwareImage == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((SlotAOffset == NULL) || (SlotBOffset == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check EFS structure of firmware image
+  //
+  EfsAddressPtr = (FIRMWARE_ENTRY_TABLEV2 *)(UINTN)((UINT8 *)SystemFirmwareImage + EFS_LOCATION);
+  if (EfsAddressPtr->Signature != FIRMWARE_TABLE_SIGNATURE) {
+    DEBUG ((DEBUG_ERROR, "EFS signature incorrect.\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Check PSP_L1_DIRECTORY of firmware image
+  //
+  DEBUG ((DEBUG_INFO, "Base Address for PSP directory: 0x%x\n", EfsAddressPtr->PspDirBase));
+  PspL1DirectoryPtr = (PSP_DIRECTORY *)(UINTN)((UINT8 *)SystemFirmwareImage + EfsAddressPtr->PspDirBase);
+  if ((PspL1DirectoryPtr->Header.Cookie != PSP_DIRECTORY_HEADER_SIGNATURE) ||
+      (!IS_VALID_ADDR32 (EfsAddressPtr->PspDirBase)) ||
+      (!ALIGN_4K_CHECK (EfsAddressPtr->PspDirBase)) ||
+      (PspL1DirectoryPtr->Header.TotalEntries == 0) ||
+      (PspL1DirectoryPtr->Header.TotalEntries > MAX_IMAGE_SLOT_COUNT)
+      )
+  {
+    DEBUG ((DEBUG_ERROR, "PSP L1 directory address, slot count or signature error!\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Check Image Slot entries of firmware image
+  //
+  SlotCount = PspL1DirectoryPtr->Header.TotalEntries;
+  for (Index = 0; Index < SlotCount; Index++) {
+    if (((PspL1DirectoryPtr->PspEntry[Index].Type.Value != PSP_REGION_A_DIR) &&
+         (PspL1DirectoryPtr->PspEntry[Index].Type.Value != PSP_REGION_B_DIR)) ||
+        (!IS_VALID_ADDR32 (PspL1DirectoryPtr->PspEntry[Index].Location)) ||
+        (!ALIGN_4K_CHECK (PspL1DirectoryPtr->PspEntry[Index].Location)) ||
+        (((PspL1DirectoryPtr->PspEntry[Index].Location) & 0xFFFFFFFF00000000) != 0)
+        )
+    {
+      DEBUG ((DEBUG_ERROR, "PSP L1 directory slot %d data error!\n", Index));
+      return EFI_NOT_FOUND;
+    }
+  }
+
+  //
+  // Get offset of specific slot
+  //
+  IshSlotAInfoPtr = (IMAGE_SLOT_HEADER *)(UINTN)((UINT8 *)SystemFirmwareImage + PspL1DirectoryPtr->PspEntry[0].Location);
+  *SlotAOffset    = IshSlotAInfoPtr->ImageSlotAddr;
+  DEBUG ((DEBUG_ERROR, "Slot A image offset: 0x%x\n", *SlotAOffset));
+
+  IshSlotBInfoPtr = (IMAGE_SLOT_HEADER *)(UINTN)((UINT8 *)SystemFirmwareImage + PspL1DirectoryPtr->PspEntry[1].Location);
+  *SlotBOffset    = IshSlotBInfoPtr->ImageSlotAddr;
+  DEBUG ((DEBUG_ERROR, "Slot B image offset: 0x%x\n", *SlotBOffset));
+
+  if ((*SlotAOffset == 0) || (*SlotBOffset == 0)) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (ActiveSlot != NULL) {
+    if (IshSlotAInfoPtr->Priority > IshSlotBInfoPtr->Priority) {
+      *ActiveSlot = SLOT_A;
+    } else {
+      *ActiveSlot = SLOT_B;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Verify layout of OTA Capsule firmware image, and return offset and size of required update slot.
+
+  @param[in]  SystemFirmwareImage     Points to the System firmware image.
+  @param[in]  UpdateSlot              The slot number need to be updated.
+  @param[out] UpdateOffset            The firmware image offset need to updated.
+  @param[out] UpdateSize              The firmware image size need to updated.
+
+  @retval EFI_SUCCESS                 Verify OTA capsule image and get updated offset/size successfully.
+  @retval others                      Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+VerifyImageLayout (
+  IN  VOID    *SystemFirmwareImage,
+  IN  UINT8   UpdateSlot,
+  OUT UINT32  *UpdateOffset,
+  OUT UINT32  *UpdateSize
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      OtaSlotAOffset;
+  UINT32      OtaSlotBOffset;
+  UINT32      FlashSlotAOffset;
+  UINT32      FlashSlotBOffset;
+  UINT8       CurrentActiveSlot;
+
+  if (SystemFirmwareImage == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((UpdateOffset == NULL) || (UpdateSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OtaSlotAOffset   = 0;
+  OtaSlotBOffset   = 0;
+  FlashSlotAOffset = 0;
+  FlashSlotBOffset = 0;
+
+  //
+  // Get image layout of OTA Capsule
+  //
+  DEBUG ((DEBUG_INFO, "Get image layout of OTA Capsule.\n"));
+  Status = GetImageLayout (SystemFirmwareImage, &OtaSlotAOffset, &OtaSlotBOffset, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "GetImageLayout of Capsule failed: %r\n", Status));
+    return Status;
+  }
+
+  //
+  // Get image layout of firmware in flash ROM
+  //
+  DEBUG ((DEBUG_INFO, "Get image layout of flash ROM.\n"));
+  Status = GetImageLayout ((VOID *)(UINTN)(PcdGet32 (PcdFlashAreaBaseAddress)), &FlashSlotAOffset, &FlashSlotBOffset, &CurrentActiveSlot);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "GetImageLayout of Flash failed: %r\n", Status));
+    return Status;
+  }
+
+  //
+  // Check current active slot and update slot
+  //
+  // -  if (CurrentActiveSlot == mUpdateSlot) {
+  // -   DEBUG ((DEBUG_ERROR, "Can't update Capsule on current active slot. CurrentActiveSlot: %d, UpdateSlot: %d\n", CurrentActiveSlot, mUpdateSlot));
+  // -   return EFI_INVALID_PARAMETER;
+  // -  }
+  //
+  // Compare layout of OTA capsule image and flash firmware
+  //
+  if ((OtaSlotAOffset != FlashSlotAOffset) || (OtaSlotBOffset != FlashSlotBOffset)) {
+    DEBUG ((DEBUG_ERROR, "Layout is different between Capsule and Flash.\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  if (UpdateSlot == SLOT_A) {
+    *UpdateOffset = OtaSlotAOffset;
+  } else if (UpdateSlot == SLOT_B) {
+    *UpdateOffset = OtaSlotBOffset;
+  } else {
+    DEBUG ((DEBUG_ERROR, "Invalid update slot number: %d\n", UpdateSlot));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // -  *UpdateSize = (UINT32) DivU64x64Remainder ((UINTN) PcdGet32 (PcdFlashAreaSize) - OtaSlotAOffset, 2, NULL);
+  *UpdateSize = (UINT32)((UINTN)PcdGet32 (PcdFlashAreaSize) - OtaSlotAOffset);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get OTA Capsule firmware image info.
+
+  @param[in]  SystemFirmwareImage     Points to the System firmware image.
+  @param[in]  SystemFirmwareImageSize The length of the System Firmware image in bytes.
+  @param[out] OtaCapsuleOffset        The firmware image offset need to updated.
+  @param[out] OtaCapsuleSize          The firmware image size need to updated.
+
+  @retval EFI_SUCCESS                 Get OTA Capsule firmware image info successfully.
+  @retval others                      Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+GetOtaCapsuleInfo (
+  IN VOID     *SystemFirmwareImage,
+  IN UINTN    SystemFirmwareImageSize,
+  OUT UINT32  *OtaCapsuleOffset,
+  OUT UINT32  *OtaCapsuleSize
+  )
+{
+  EFI_STATUS          Status;
+  OTA_CAPSULE_UPDATE  OtaCapsuleUpdateVal;
+  // -  UINTN                        VarSize;
+  UINT32  UpdateOffset;
+  UINT32  UpdateSize;
+
+  if ((OtaCapsuleOffset == NULL) || (OtaCapsuleSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((DEBUG_INFO, "GetOtaCapsuleInfo:"));
+  DEBUG ((DEBUG_INFO, "  Legnth - 0x%x\n", SystemFirmwareImageSize));
+
+  // -  if (SystemFirmwareImageSize != (UINTN) PcdGet32 (PcdFlashAreaSize)) {
+  // -    return EFI_INVALID_PARAMETER;
+  // -  }
+  if (SystemFirmwareImageSize != (UINTN)(PcdGet32 (PcdFlashAreaSize)*2)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&OtaCapsuleUpdateVal, sizeof (OTA_CAPSULE_UPDATE));
+
+  /*
+    VarSize = sizeof (OTA_CAPSULE_UPDATE);
+    Status = gRT->GetVariable (
+                    OTA_CAPSULE_VAR_NAME,
+                    &gOtaCapsuleUpdateGuid,
+                    NULL,
+                    &VarSize,
+                    (VOID *) &OtaCapsuleUpdateVal
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo: GetVariable failed: %r\n", Status));
+      return Status;
+    }
+
+    DEBUG ((DEBUG_INFO, "UpdateFlag: 0x%x, UpdateSlot: 0x%x\n", OtaCapsuleUpdateVal.UpdateFlag, OtaCapsuleUpdateVal.UpdateSlot));
+
+    mUpdateSlot = OtaCapsuleUpdateVal.UpdateSlot;
+    if (mUpdateSlot >= MAX_SLOT_NUM) {
+      DEBUG ((DEBUG_ERROR, "Invalid Slot number: %d\n", mUpdateSlot));
+      return EFI_NOT_FOUND;
+    }
+  */
+  mUpdateSlot = 0;
+
+  Status = VerifyImageLayout (SystemFirmwareImage, mUpdateSlot, &UpdateOffset, &UpdateSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "VerifyImageLayout failed: %r\n", Status));
+    return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, "UpdateSlot: %d, UpdateOffset: 0x%x, UpdateSize: 0x%x\n", mUpdateSlot, UpdateOffset, UpdateSize));
+
+  *OtaCapsuleOffset = UpdateOffset;
+  *OtaCapsuleSize   = UpdateSize;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get OTA Capsule firmware image info.
+
+  @param[in]  SystemFirmwareImage     Points to the System firmware image.
+  @param[in]  SystemFirmwareImageSize The length of the System Firmware image in bytes.
+  @param[out] OtaCapsuleOffset        The firmware image offset need to updated.
+  @param[out] OtaCapsuleSize          The firmware image size need to updated.
+
+  @retval EFI_SUCCESS                 Get OTA Capsule firmware image info successfully.
+  @retval others                      Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+GetOtaCapsuleInfoSlotB (
+  IN VOID     *SystemFirmwareImage,
+  IN UINTN    SystemFirmwareImageSize,
+  OUT UINT32  *OtaCapsuleOffset,
+  OUT UINT32  *OtaCapsuleSize
+  )
+{
+  EFI_STATUS          Status;
+  OTA_CAPSULE_UPDATE  OtaCapsuleUpdateVal;
+  // -  UINTN                        VarSize;
+  UINT32  UpdateOffset;
+  UINT32  UpdateSize;
+
+  // -  if ((OtaCapsuleOffset == NULL) || (OtaCapsuleSize == NULL)) {
+  // -    return EFI_INVALID_PARAMETER;
+  // -  }
+
+  DEBUG ((DEBUG_INFO, "GetOtaCapsuleInfo:"));
+  DEBUG ((DEBUG_INFO, "  Legnth - 0x%x\n", SystemFirmwareImageSize));
+  // -  if (SystemFirmwareImageSize != (UINTN) PcdGet32 (PcdFlashAreaSize)) {
+  // -    return EFI_INVALID_PARAMETER;
+  // -  }
+  // -  if (SystemFirmwareImageSize != (UINTN) (PcdGet32 (PcdFlashAreaSize)*2)) {
+  // -    return EFI_INVALID_PARAMETER;
+  // -  }
+  ZeroMem (&OtaCapsuleUpdateVal, sizeof (OTA_CAPSULE_UPDATE));
+
+  /*
+    VarSize = sizeof (OTA_CAPSULE_UPDATE);
+    Status = gRT->GetVariable (
+                    OTA_CAPSULE_VAR_NAME,
+                    &gOtaCapsuleUpdateGuid,
+                    NULL,
+                    &VarSize,
+                    (VOID *) &OtaCapsuleUpdateVal
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo: GetVariable failed: %r\n", Status));
+      return Status;
+    }
+
+    DEBUG ((DEBUG_INFO, "UpdateFlag: 0x%x, UpdateSlot: 0x%x\n", OtaCapsuleUpdateVal.UpdateFlag, OtaCapsuleUpdateVal.UpdateSlot));
+
+    mUpdateSlot = OtaCapsuleUpdateVal.UpdateSlot;
+    if (mUpdateSlot >= MAX_SLOT_NUM) {
+      DEBUG ((DEBUG_ERROR, "Invalid Slot number: %d\n", mUpdateSlot));
+      return EFI_NOT_FOUND;
+    }
+  */
+  mUpdateSlot = 1;
+
+  Status = VerifyImageLayout (SystemFirmwareImage, mUpdateSlot, &UpdateOffset, &UpdateSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "VerifyImageLayout failed: %r\n", Status));
+    return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, "UpdateSlot: %d, UpdateOffset: 0x%x, UpdateSize: 0x%x\n", mUpdateSlot, UpdateOffset, UpdateSize));
+
+  *OtaCapsuleOffset = UpdateOffset;
+  *OtaCapsuleSize   = UpdateSize;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Update active slot information in ISH.
+
+  @param[in]  SlotNum                 The slot number will be set as active.
+
+  @retval EFI_SUCCESS                 Set active slto successfully.
+  @retval others                      Some error occurs when executing this routine.
+
+**/
+EFI_STATUS
+UpdateAbActiveSlot (
+  IN UINT8  SlotNum
+  )
+{
+  EFI_STATUS              Status;
+  IMAGE_SLOT_HEADER_INFO  IshInfo;
+  UINTN                   VarSize;
+
+  DEBUG ((DEBUG_INFO, "UpdateAbActiveSlot...\n"));
+
+  if (SlotNum >= MAX_SLOT_NUM) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&IshInfo, sizeof (IMAGE_SLOT_HEADER_INFO));
+
+  VarSize = sizeof (IMAGE_SLOT_HEADER_INFO);
+  Status  = gRT->GetVariable (
+                   ISH_VAR_NAME,
+                   &gABSupportUpdateIshGuid,
+                   NULL,
+                   &VarSize,
+                   (VOID *)&IshInfo
+                   );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Get A/B slot info failed: %r\n", Status));
+    return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, "Get IshInfo.SlotA_Priority:      0x%x\n", IshInfo.SlotA_Priority));
+  DEBUG ((DEBUG_INFO, "Get IshInfo.SlotA_UpdateRetries: 0x%x\n", IshInfo.SlotA_UpdateRetries));
+  DEBUG ((DEBUG_INFO, "Get IshInfo.SlotA_GlitchRetries: 0x%x\n", IshInfo.SlotA_GlitchRetries));
+  DEBUG ((DEBUG_INFO, "Get IshInfo.SlotB_Priority:      0x%x\n", IshInfo.SlotB_Priority));
+  DEBUG ((DEBUG_INFO, "Get IshInfo.SlotB_UpdateRetries: 0x%x\n", IshInfo.SlotB_UpdateRetries));
+  DEBUG ((DEBUG_INFO, "Get IshInfo.SlotB_GlitchRetries: 0x%x\n\n", IshInfo.SlotB_GlitchRetries));
+
+  if (SlotNum == SLOT_A) {
+    // Slot A
+    if (IshInfo.SlotB_Priority == MAX_UINT32) {
+      IshInfo.SlotA_Priority = PcdGet32 (PcdFlashAbImageSlotDefaultPriority);
+      IshInfo.SlotB_Priority = IshInfo.SlotA_Priority - 1;
+    } else {
+      IshInfo.SlotA_Priority = MAX (IshInfo.SlotA_Priority, IshInfo.SlotB_Priority) + 1;
+    }
+
+    IshInfo.SlotA_UpdateRetries = 0xFF;
+  } else if (SlotNum == SLOT_B) {
+    // Slot B
+    if (IshInfo.SlotA_Priority == MAX_UINT32) {
+      IshInfo.SlotB_Priority = PcdGet32 (PcdFlashAbImageSlotDefaultPriority);
+      IshInfo.SlotA_Priority = IshInfo.SlotB_Priority - 1;
+    } else {
+      IshInfo.SlotB_Priority = MAX (IshInfo.SlotA_Priority, IshInfo.SlotB_Priority) + 1;
+    }
+
+    IshInfo.SlotB_UpdateRetries = 0xFF;
+  }
+
+  DEBUG ((DEBUG_INFO, "Set IshInfo.SlotA_Priority:      0x%x\n", IshInfo.SlotA_Priority));
+  DEBUG ((DEBUG_INFO, "Set IshInfo.SlotA_UpdateRetries: 0x%x\n", IshInfo.SlotA_UpdateRetries));
+  DEBUG ((DEBUG_INFO, "Set IshInfo.SlotA_GlitchRetries: 0x%x\n", IshInfo.SlotA_GlitchRetries));
+  DEBUG ((DEBUG_INFO, "Set IshInfo.SlotB_Priority:      0x%x\n", IshInfo.SlotB_Priority));
+  DEBUG ((DEBUG_INFO, "Set IshInfo.SlotB_UpdateRetries: 0x%x\n", IshInfo.SlotB_UpdateRetries));
+  DEBUG ((DEBUG_INFO, "Set IshInfo.SlotB_GlitchRetries: 0x%x\n", IshInfo.SlotB_GlitchRetries));
+
+  Status = gRT->SetVariable (
+                  ISH_VAR_NAME,
+                  &gABSupportUpdateIshGuid,
+                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+                  sizeof (IMAGE_SLOT_HEADER_INFO),
+                  (VOID *)&IshInfo
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Set Slot info failed: %r\n", Status));
+    return Status;
+  }
+
+  return Status;
+}
+
+/**
+  Update System Firmware image.
+
+  @param[in]  SystemFirmwareImage     Points to the System Firmware image.
+  @param[in]  SystemFirmwareImageSize The length of the System Firmware image in bytes.
+  @param[in]  ConfigImage             Points to the config file image.
+  @param[in]  ConfigImageSize         The length of the config file image in bytes.
+  @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[in]  Progress                A function used by the driver to report the progress of the firmware update.
+
+  @retval EFI_SUCCESS             The System Firmware image is updated.
+  @retval EFI_WRITE_PROTECTED     The flash device is read only.
+**/
+EFI_STATUS
+UpdateImage (
+  IN VOID                                           *SystemFirmwareImage,
+  IN UINTN                                          SystemFirmwareImageSize,
+  IN VOID                                           *ConfigImage,
+  IN UINTN                                          ConfigImageSize,
+  OUT UINT32                                        *LastAttemptVersion,
+  OUT UINT32                                        *LastAttemptStatus,
+  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress
+  )
+{
+  EFI_STATUS          Status;
+  UPDATE_CONFIG_DATA  *ConfigData;
+  UPDATE_CONFIG_DATA  *UpdateConfigData;
+  CONFIG_HEADER       ConfigHeader;
+  UINTN               Index;
+  UINTN               TotalSize;
+  UINTN               BytesWritten;
+  UINTN               StartPercentage;
+  UINTN               EndPercentage;
+  UINT32              OtaCapsuleOffset;
+  UINT32              OtaCapsuleSize;
+  UINT32              ECImageSize;
+  UINT32              ECImageOffset;
+
+  if (ConfigImage == NULL) {
+    DEBUG ((DEBUG_INFO, "PlatformUpdate (NoConfig):"));
+    // ASSUME the whole System Firmware include NVRAM region.
+    StartPercentage = 0;
+    EndPercentage   = 100;
+    if (Progress != NULL) {
+      Progress (StartPercentage);
+    }
+
+    ECImageSize   = 0x20000;
+    ECImageOffset = 0x0;
+
+    DEBUG ((DEBUG_INFO, "  BaseAddress - 0x%x,", ECImageOffset));
+    DEBUG ((DEBUG_INFO, "  Length - 0x%x\n", ECImageSize));
+
+    Status = PerformFlashWriteWithProgress (
+               PlatformFirmwareTypeNvRam,
+               (EFI_PHYSICAL_ADDRESS)ECImageOffset,
+               FlashAddressTypeRelativeAddress,
+               (VOID *)((UINT8 *)SystemFirmwareImage + ECImageOffset),
+               ECImageSize,
+               Progress,
+               StartPercentage,
+               EndPercentage
+               );
+    if (Progress != NULL) {
+      Progress (EndPercentage);
+    }
+
+    if (!EFI_ERROR (Status)) {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+      mNvRamUpdated      = TRUE;
+    } else {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+    }
+
+    StartPercentage = 0;
+    EndPercentage   = 100;
+    if (Progress != NULL) {
+      Progress (StartPercentage);
+    }
+
+    Status = GetOtaCapsuleInfo (SystemFirmwareImage, SystemFirmwareImageSize, &OtaCapsuleOffset, &OtaCapsuleSize);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo failed: %r\n", Status));
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+      return Status;
+    }
+
+    DEBUG ((DEBUG_INFO, "  BaseAddress - 0x%x,", OtaCapsuleOffset));
+    DEBUG ((DEBUG_INFO, "  Length - 0x%x\n", OtaCapsuleSize));
+
+    Status = PerformFlashWriteWithProgress (
+               PlatformFirmwareTypeNvRam,
+               (EFI_PHYSICAL_ADDRESS)OtaCapsuleOffset,
+               FlashAddressTypeRelativeAddress,
+               (VOID *)((UINT8 *)SystemFirmwareImage + OtaCapsuleOffset),
+               OtaCapsuleSize,
+               Progress,
+               StartPercentage,
+               EndPercentage
+               );
+    if (Progress != NULL) {
+      Progress (EndPercentage);
+    }
+
+    if (!EFI_ERROR (Status)) {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+      mNvRamUpdated      = TRUE;
+    } else {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+    }
+
+    Status = GetOtaCapsuleInfoSlotB (SystemFirmwareImage, SystemFirmwareImageSize, &OtaCapsuleOffset, &OtaCapsuleSize);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo failed: %r\n", Status));
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+      return Status;
+    }
+
+    DEBUG ((DEBUG_INFO, "  BaseAddress - 0x%x,", OtaCapsuleOffset));
+    DEBUG ((DEBUG_INFO, "  Length - 0x%x\n", OtaCapsuleSize));
+
+    Status = PerformFlashWriteWithProgress (
+               PlatformFirmwareTypeNvRam,
+               (EFI_PHYSICAL_ADDRESS)OtaCapsuleOffset,
+               FlashAddressTypeRelativeAddress,
+               (VOID *)((UINT8 *)SystemFirmwareImage + OtaCapsuleOffset),
+               OtaCapsuleSize,
+               Progress,
+               StartPercentage,
+               EndPercentage
+               );
+    if (Progress != NULL) {
+      Progress (EndPercentage);
+    }
+
+    if (!EFI_ERROR (Status)) {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
+      mNvRamUpdated      = TRUE;
+    } else {
+      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+    }
+
+    return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, "PlatformUpdate (With Config):\n"));
+  ConfigData = NULL;
+  ZeroMem (&ConfigHeader, sizeof (ConfigHeader));
+  Status = ParseUpdateDataFile (
+             ConfigImage,
+             ConfigImageSize,
+             &ConfigHeader,
+             &ConfigData
+             );
+  DEBUG ((DEBUG_INFO, "ParseUpdateDataFile - %r\n", Status));
+  if (EFI_ERROR (Status)) {
+    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((DEBUG_INFO, "ConfigHeader.NumOfUpdates - 0x%x\n", ConfigHeader.NumOfUpdates));
+  DEBUG ((DEBUG_INFO, "PcdEdkiiSystemFirmwareFileGuid - %g\n", PcdGetPtr (PcdEdkiiSystemFirmwareFileGuid)));
+
+  TotalSize = 0;
+  for (Index = 0; Index < ConfigHeader.NumOfUpdates; Index++) {
+    if (CompareGuid (&ConfigData[Index].FileGuid, PcdGetPtr (PcdEdkiiSystemFirmwareFileGuid))) {
+      TotalSize = TotalSize + ConfigData[Index].Length;
+    }
+  }
+
+  BytesWritten     = 0;
+  Index            = 0;
+  UpdateConfigData = ConfigData;
+  while (Index < ConfigHeader.NumOfUpdates) {
+    if (CompareGuid (&UpdateConfigData->FileGuid, PcdGetPtr (PcdEdkiiSystemFirmwareFileGuid))) {
+      DEBUG ((DEBUG_INFO, "FileGuid - %g (processing)\n", &UpdateConfigData->FileGuid));
+      StartPercentage = (BytesWritten * 100) / TotalSize;
+      EndPercentage   = ((BytesWritten + UpdateConfigData->Length) * 100) / TotalSize;
+      Status          = PerformUpdate (
+                          SystemFirmwareImage,
+                          SystemFirmwareImageSize,
+                          UpdateConfigData,
+                          LastAttemptVersion,
+                          LastAttemptStatus,
+                          Progress,
+                          StartPercentage,
+                          EndPercentage
+                          );
+      //
+      // Shall updates be serialized so that if an update is not successfully completed,
+      // the remaining updates won't be performed.
+      //
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+    } else {
+      DEBUG ((DEBUG_INFO, "FileGuid - %g (ignored)\n", &UpdateConfigData->FileGuid));
+    }
+
+    BytesWritten += UpdateConfigData->Length;
+
+    Index++;
+    UpdateConfigData++;
+  }
+
+  return Status;
+}
+
+/**
+  Authenticate and update System Firmware image.
+
+  Caution: This function may receive untrusted input.
+
+  @param[in]  Image              The EDKII system FMP capsule image.
+  @param[in]  ImageSize          The size of the EDKII system FMP capsule image in bytes.
+  @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[out] LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+
+  @retval EFI_SUCCESS             EDKII system FMP capsule passes authentication and the System Firmware image is updated.
+  @retval EFI_SECURITY_VIOLATION  EDKII system FMP capsule fails authentication and the System Firmware image is not updated.
+  @retval EFI_WRITE_PROTECTED     The flash device is read only.
+**/
+EFI_STATUS
+SystemFirmwareAuthenticatedUpdate (
+  IN VOID                                           *Image,
+  IN UINTN                                          ImageSize,
+  OUT UINT32                                        *LastAttemptVersion,
+  OUT UINT32                                        *LastAttemptStatus,
+  IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress
+  )
+{
+  EFI_STATUS  Status;
+  VOID        *SystemFirmwareImage;
+  UINTN       SystemFirmwareImageSize;
+  VOID        *ConfigImage;
+  UINTN       ConfigImageSize;
+  VOID        *AuthenticatedImage;
+  UINTN       AuthenticatedImageSize;
+
+  AuthenticatedImage     = NULL;
+  AuthenticatedImageSize = 0;
+
+  DEBUG ((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate...\n"));
+
+  Status = CapsuleAuthenticateSystemFirmware (Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "SystemFirmwareAuthenticateImage - %r\n", Status));
+    return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, "ExtractSystemFirmwareImage ...\n"));
+  ExtractSystemFirmwareImage (AuthenticatedImage, AuthenticatedImageSize, &SystemFirmwareImage, &SystemFirmwareImageSize);
+  DEBUG ((DEBUG_INFO, "ExtractConfigImage ...\n"));
+  ExtractConfigImage (AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize);
+
+  DEBUG ((DEBUG_INFO, "UpdateImage ...\n"));
+  Status = UpdateImage (SystemFirmwareImage, SystemFirmwareImageSize, ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus, Progress);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "UpdateImage - %r\n", Status));
+    return Status;
+  }
+
+ #if 0
+  // DO NOT KNOW THE REASON to update A/B Active Slot.
+  // Removed FOR NOW.
+
+  //
+  // Update A/B active slot info
+  //
+  Status = UpdateAbActiveSlot (mUpdateSlot);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "UpdateAbActiveSlot failed: %r\n", Status));
+    return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate Done\n"));
+ #endif
+  return Status;
+}
+
+/**
+
+  This code finds variable in storage blocks (Volatile or Non-Volatile).
+
+  @param[in]      VariableName               Name of Variable to be found.
+  @param[in]      VendorGuid                 Variable vendor GUID.
+  @param[out]     Attributes                 Attribute value of the variable found.
+  @param[in, out] DataSize                   Size of Data found. If size is less than the
+                                             data, this value contains the required size.
+  @param[out]     Data                       Data pointer.
+
+  @return EFI_INVALID_PARAMETER     Invalid parameter.
+  @return EFI_SUCCESS               Find the specified variable.
+  @return EFI_NOT_FOUND             Not found.
+  @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.
+
+**/
+EFI_STATUS
+EFIAPI
+GetVariableHook (
+  IN      CHAR16    *VariableName,
+  IN      EFI_GUID  *VendorGuid,
+  OUT     UINT32    *Attributes OPTIONAL,
+  IN OUT  UINTN     *DataSize,
+  OUT     VOID      *Data
+  )
+{
+  DEBUG ((DEBUG_INFO, "GetVariableHook - %S, %g\n", VariableName, VendorGuid));
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+
+  This code Finds the Next available variable.
+
+  @param[in, out] VariableNameSize           Size of the variable name.
+  @param[in, out] VariableName               Pointer to variable name.
+  @param[in, out] VendorGuid                 Variable Vendor Guid.
+
+  @return EFI_INVALID_PARAMETER     Invalid parameter.
+  @return EFI_SUCCESS               Find the specified variable.
+  @return EFI_NOT_FOUND             Not found.
+  @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextVariableNameHook (
+  IN OUT  UINTN     *VariableNameSize,
+  IN OUT  CHAR16    *VariableName,
+  IN OUT  EFI_GUID  *VendorGuid
+  )
+{
+  DEBUG ((DEBUG_INFO, "GetNextVariableNameHook - %S, %g\n", VariableName, VendorGuid));
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+
+  This code sets variable in storage blocks (Volatile or Non-Volatile).
+
+  @param[in] VariableName                     Name of Variable to be found.
+  @param[in] VendorGuid                       Variable vendor GUID.
+  @param[in] Attributes                       Attribute value of the variable found
+  @param[in] DataSize                         Size of Data found. If size is less than the
+                                              data, this value contains the required size.
+  @param[in] Data                             Data pointer.
+
+  @return EFI_INVALID_PARAMETER           Invalid parameter.
+  @return EFI_SUCCESS                     Set successfully.
+  @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable.
+  @return EFI_NOT_FOUND                   Not found.
+  @return EFI_WRITE_PROTECTED             Variable is read-only.
+
+**/
+EFI_STATUS
+EFIAPI
+SetVariableHook (
+  IN CHAR16    *VariableName,
+  IN EFI_GUID  *VendorGuid,
+  IN UINT32    Attributes,
+  IN UINTN     DataSize,
+  IN VOID      *Data
+  )
+{
+  DEBUG ((DEBUG_INFO, "SetVariableHook - %S, %g, 0x%x (0x%x)\n", VariableName, VendorGuid, Attributes, DataSize));
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+
+  This code returns information about the EFI variables.
+
+  @param[in]  Attributes                     Attributes bitmask to specify the type of variables
+                                             on which to return information.
+  @param[out] MaximumVariableStorageSize     Pointer to the maximum size of the storage space available
+                                             for the EFI variables associated with the attributes specified.
+  @param[out] RemainingVariableStorageSize   Pointer to the remaining size of the storage space available
+                                             for EFI variables associated with the attributes specified.
+  @param[out] MaximumVariableSize            Pointer to the maximum size of an individual EFI variables
+                                             associated with the attributes specified.
+
+  @return EFI_SUCCESS                   Query successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+QueryVariableInfoHook (
+  IN  UINT32  Attributes,
+  OUT UINT64  *MaximumVariableStorageSize,
+  OUT UINT64  *RemainingVariableStorageSize,
+  OUT UINT64  *MaximumVariableSize
+  )
+{
+  DEBUG ((DEBUG_INFO, "QueryVariableInfoHook - 0x%x\n", Attributes));
+  return EFI_NOT_AVAILABLE_YET;
+}
+
+/**
+  Updates the firmware image of the device.
+
+  This function updates the hardware with the new firmware image.
+  This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+  If the firmware image is updatable, the function should perform the following minimal validations
+  before proceeding to do the firmware image update.
+  - Validate the image authentication if image has attribute
+    IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+    EFI_SECURITY_VIOLATION if the validation fails.
+  - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+    the image is unsupported. The function can optionally provide more detailed information on
+    why the image is not a supported image.
+  - Validate the data from VendorCode if not null. Image validation must be performed before
+    VendorCode data validation. VendorCode data is ignored or considered invalid if image
+    validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+  VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+  the caller did not specify the policy or use the default policy. As an example, vendor can implement
+  a policy to allow an option to force a firmware image update when the abort reason is due to the new
+  firmware image version is older than the current firmware image version or bad image checksum.
+  Sensitive operations such as those wiping the entire firmware image and render the device to be
+  non-functional should be encoded in the image itself rather than passed with the VendorCode.
+  AbortReason enables vendor to have the option to provide a more detailed description of the abort
+  reason to the caller.
+
+  @param[in]  This               A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+  @param[in]  ImageIndex         A unique number identifying the firmware image(s) within the device.
+                                 The number is between 1 and DescriptorCount.
+  @param[in]  Image              Points to the new image.
+  @param[in]  ImageSize          Size of the new image in bytes.
+  @param[in]  VendorCode         This enables vendor to implement vendor-specific firmware image update policy.
+                                 Null indicates the caller did not specify the policy or use the default policy.
+  @param[in]  Progress           A function used by the driver to report the progress of the firmware update.
+  @param[out] AbortReason        A pointer to a pointer to a null-terminated string providing more
+                                 details for the aborted operation. The buffer is allocated by this function
+                                 with AllocatePool(), and it is the caller's responsibility to free it with a
+                                 call to FreePool().
+
+  @retval EFI_SUCCESS            The device was successfully updated with the new image.
+  @retval EFI_ABORTED            The operation is aborted.
+  @retval EFI_INVALID_PARAMETER  The Image was NULL.
+  @retval EFI_UNSUPPORTED        The operation is not supported.
+  @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpSetImage (
+  IN  EFI_FIRMWARE_MANAGEMENT_PROTOCOL               *This,
+  IN  UINT8                                          ImageIndex,
+  IN  CONST VOID                                     *Image,
+  IN  UINTN                                          ImageSize,
+  IN  CONST VOID                                     *VendorCode,
+  IN  EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS  Progress,
+  OUT CHAR16                                         **AbortReason
+  )
+{
+  EFI_STATUS               Status;
+  EFI_STATUS               VarStatus;
+  SYSTEM_FMP_PRIVATE_DATA  *SystemFmpPrivate;
+
+  if ((Image == NULL) || (ImageSize == 0) || (AbortReason == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  SystemFmpPrivate = SYSTEM_FMP_PRIVATE_DATA_FROM_FMP (This);
+  *AbortReason     = NULL;
+
+  if ((ImageIndex == 0) || (ImageIndex > SystemFmpPrivate->DescriptorCount)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = SystemFirmwareAuthenticatedUpdate ((VOID *)Image, ImageSize, &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate->LastAttempt.LastAttemptStatus, Progress);
+  DEBUG ((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus));
+
+  //
+  // If NVRAM is updated, we should no longer touch variable services, because
+  // the current variable driver may not manage the new NVRAM region.
+  //
+  if (mNvRamUpdated) {
+    DEBUG ((DEBUG_INFO, "NvRamUpdated, Update Variable Serivces\n"));
+    gRT->GetVariable         = GetVariableHook;
+    gRT->GetNextVariableName = GetNextVariableNameHook;
+    gRT->SetVariable         = SetVariableHook;
+    gRT->QueryVariableInfo   = QueryVariableInfoHook;
+
+    gRT->Hdr.CRC32 = 0;
+    gBS->CalculateCrc32 (
+           (UINT8 *)&gRT->Hdr,
+           gRT->Hdr.HeaderSize,
+           &gRT->Hdr.CRC32
+           );
+  }
+
+  VarStatus = gRT->SetVariable (
+                     SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME,
+                     &gSystemFmpLastAttemptVariableGuid,
+                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                     sizeof (SystemFmpPrivate->LastAttempt),
+                     &SystemFmpPrivate->LastAttempt
+                     );
+  DEBUG ((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus));
+
+  return Status;
+}
+
+/**
+  Get the set of EFI_FIRMWARE_IMAGE_DESCRIPTOR structures from an FMP Protocol.
+
+  @param[in]  Handle             Handle with an FMP Protocol or a System FMP
+                                 Protocol.
+  @param[in]  ProtocolGuid       Pointer to the FMP Protocol GUID or System FMP
+                                 Protocol GUID.
+  @param[out] FmpImageInfoCount  Pointer to the number of
+                                 EFI_FIRMWARE_IMAGE_DESCRIPTOR structures.
+  @param[out] DescriptorSize     Pointer to the size, in bytes, of each
+                                 EFI_FIRMWARE_IMAGE_DESCRIPTOR structure.
+
+  @return NULL   No EFI_FIRMWARE_IMAGE_DESCRIPTOR structures found.
+  @return !NULL  Pointer to a buffer of EFI_FIRMWARE_IMAGE_DESCRIPTOR structures
+                 allocated using AllocatePool().  Caller must free buffer with
+                 FreePool().
+**/
+EFI_FIRMWARE_IMAGE_DESCRIPTOR *
+GetFmpImageDescriptors (
+  IN  EFI_HANDLE  Handle,
+  IN  EFI_GUID    *ProtocolGuid,
+  OUT UINT8       *FmpImageInfoCount,
+  OUT UINTN       *DescriptorSize
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *Fmp;
+  UINTN                             ImageInfoSize;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR     *FmpImageInfoBuf;
+  UINT32                            FmpImageInfoDescriptorVer;
+  UINT32                            PackageVersion;
+  CHAR16                            *PackageVersionName;
+
+  *FmpImageInfoCount = 0;
+  *DescriptorSize    = 0;
+
+  Status = gBS->HandleProtocol (
+                  Handle,
+                  ProtocolGuid,
+                  (VOID **)&Fmp
+                  );
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  //
+  // Determine the size required for the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  //
+  ImageInfoSize = 0;
+  Status        = Fmp->GetImageInfo (
+                         Fmp,                        // FMP Pointer
+                         &ImageInfoSize,             // Buffer Size (in this case 0)
+                         NULL,                       // NULL so we can get size
+                         &FmpImageInfoDescriptorVer, // DescriptorVersion
+                         FmpImageInfoCount,          // DescriptorCount
+                         DescriptorSize,             // DescriptorSize
+                         &PackageVersion,            // PackageVersion
+                         &PackageVersionName         // PackageVersionName
+                         );
+  if (Status != EFI_BUFFER_TOO_SMALL) {
+    DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Unexpected Failure.  Status = %r\n", Status));
+    return NULL;
+  }
+
+  //
+  // Allocate buffer for the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  //
+  FmpImageInfoBuf = NULL;
+  FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
+  if (FmpImageInfoBuf == NULL) {
+    DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to allocate memory for descriptors.\n"));
+    return NULL;
+  }
+
+  //
+  // Retrieve the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+  //
+  PackageVersionName = NULL;
+  Status             = Fmp->GetImageInfo (
+                              Fmp,
+                              &ImageInfoSize,             // ImageInfoSize
+                              FmpImageInfoBuf,            // ImageInfo
+                              &FmpImageInfoDescriptorVer, // DescriptorVersion
+                              FmpImageInfoCount,          // DescriptorCount
+                              DescriptorSize,             // DescriptorSize
+                              &PackageVersion,            // PackageVersion
+                              &PackageVersionName         // PackageVersionName
+                              );
+
+  //
+  // Free unused PackageVersionName return buffer
+  //
+  if (PackageVersionName != NULL) {
+    FreePool (PackageVersionName);
+    PackageVersionName = NULL;
+  }
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failure in GetImageInfo.  Status = %r\n", Status));
+    if (FmpImageInfoBuf != NULL) {
+      FreePool (FmpImageInfoBuf);
+    }
+
+    return NULL;
+  }
+
+  return FmpImageInfoBuf;
+}
+
+/**
+  Search for handles with an FMP protocol whose EFI_FIRMWARE_IMAGE_DESCRIPTOR
+  ImageTypeId matches the ImageTypeId produced by this module.
+
+  @param[in]  ProtocolGuid  Pointer to the GUID of the protocol to search.
+  @param[out] HandleCount   Pointer to the number of returned handles.
+
+  @return NULL   No matching handles found.
+  @return !NULL  Pointer to a buffer of handles allocated using AllocatePool().
+                 Caller must free buffer with FreePool().
+**/
+EFI_HANDLE *
+FindMatchingFmpHandles (
+  IN  EFI_GUID  *ProtocolGuid,
+  OUT UINTN     *HandleCount
+  )
+{
+  EFI_STATUS                     Status;
+  UINTN                          TempHandleCount;
+  EFI_HANDLE                     *HandleBuffer;
+  UINTN                          Index;
+  UINTN                          Index2;
+  UINTN                          Index3;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *OriginalFmpImageInfoBuf;
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR  *FmpImageInfoBuf;
+  UINT8                          FmpImageInfoCount;
+  UINTN                          DescriptorSize;
+  BOOLEAN                        MatchFound;
+
+  *HandleCount    = 0;
+  TempHandleCount = 0;
+  HandleBuffer    = NULL;
+  Status          = gBS->LocateHandleBuffer (
+                           ByProtocol,
+                           ProtocolGuid,
+                           NULL,
+                           &TempHandleCount,
+                           &HandleBuffer
+                           );
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  for (Index = 0; Index < TempHandleCount; Index++) {
+    OriginalFmpImageInfoBuf = GetFmpImageDescriptors (
+                                HandleBuffer[Index],
+                                ProtocolGuid,
+                                &FmpImageInfoCount,
+                                &DescriptorSize
+                                );
+
+    //
+    // Loop through the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+    //
+    MatchFound = FALSE;
+    if (OriginalFmpImageInfoBuf != NULL) {
+      FmpImageInfoBuf = OriginalFmpImageInfoBuf;
+
+      for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
+        for (Index3 = 0; Index3 < mSystemFmpPrivate->DescriptorCount; Index3++) {
+          MatchFound = CompareGuid (
+                         &FmpImageInfoBuf->ImageTypeId,
+                         &mSystemFmpPrivate->ImageDescriptor[Index3].ImageTypeId
+                         );
+          if (MatchFound) {
+            break;
+          }
+        }
+
+        if (MatchFound) {
+          break;
+        }
+
+        //
+        // Increment the buffer pointer ahead by the size of the descriptor
+        //
+        FmpImageInfoBuf = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)FmpImageInfoBuf) + DescriptorSize);
+      }
+
+      if (MatchFound) {
+        HandleBuffer[*HandleCount] = HandleBuffer[Index];
+        (*HandleCount)++;
+      }
+
+      FreePool (OriginalFmpImageInfoBuf);
+    }
+  }
+
+  if ((*HandleCount) == 0) {
+    //
+    // No any matching handle.
+    //
+    FreePool (HandleBuffer);
+    return NULL;
+  }
+
+  return HandleBuffer;
+}
+
+/**
+  Uninstall System FMP Protocol instances that may have been installed by
+  SystemFirmwareUpdateDxe drivers dispatches by other capsules.
+
+  @retval EFI_SUCCESS  All System FMP Protocols found were uninstalled.
+  @return Other        One or more System FMP Protocols could not be uninstalled.
+
+**/
+EFI_STATUS
+UninstallMatchingSystemFmpProtocols (
+  VOID
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_HANDLE                        *HandleBuffer;
+  UINTN                             HandleCount;
+  UINTN                             Index;
+  EFI_FIRMWARE_MANAGEMENT_PROTOCOL  *SystemFmp;
+
+  //
+  // Uninstall SystemFmpProtocol instances that may have been produced by
+  // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules.
+  //
+  HandleBuffer = FindMatchingFmpHandles (
+                   &gSystemFmpProtocolGuid,
+                   &HandleCount
+                   );
+  DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching System FMP instances\n", HandleCount));
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->HandleProtocol (
+                    HandleBuffer[Index],
+                    &gSystemFmpProtocolGuid,
+                    (VOID **)&SystemFmp
+                    );
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Uninstall SystemFmp produced by another capsule\n"));
+    Status = gBS->UninstallProtocolInterface (
+                    HandleBuffer[Index],
+                    &gSystemFmpProtocolGuid,
+                    SystemFmp
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to uninstall SystemFmp %r.  Exiting.\n", Status));
+      FreePool (HandleBuffer);
+      return Status;
+    }
+  }
+
+  if (HandleBuffer != NULL) {
+    FreePool (HandleBuffer);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  System FMP module entrypoint
+
+  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
+  @param[in] SystemTable  A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           System FMP module is initialized.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources avaulable to
+                                initialize this module.
+  @retval Other                 System FMP Protocols could not be uninstalled.
+  @retval Other                 System FMP Protocol could not be installed.
+  @retval Other                 FMP Protocol could not be installed.
+**/
+EFI_STATUS
+EFIAPI
+SystemFirmwareUpdateMainDxe (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HANDLE  *HandleBuffer;
+  UINTN       HandleCount;
+
+  //
+  // Initialize SystemFmpPrivateData
+  //
+  mSystemFmpPrivate = AllocateZeroPool (sizeof (SYSTEM_FMP_PRIVATE_DATA));
+  if (mSystemFmpPrivate == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = InitializePrivateData (mSystemFmpPrivate);
+  if (EFI_ERROR (Status)) {
+    FreePool (mSystemFmpPrivate);
+    mSystemFmpPrivate = NULL;
+    return Status;
+  }
+
+  //
+  // Uninstall SystemFmpProtocol instances that may have been produced by
+  // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules.
+  //
+  Status = UninstallMatchingSystemFmpProtocols ();
+  if (EFI_ERROR (Status)) {
+    FreePool (mSystemFmpPrivate);
+    mSystemFmpPrivate = NULL;
+    return Status;
+  }
+
+  //
+  // Look for a handle with matching Firmware Management Protocol
+  //
+  HandleCount  = 0;
+  HandleBuffer = FindMatchingFmpHandles (
+                   &gEfiFirmwareManagementProtocolGuid,
+                   &HandleCount
+                   );
+  DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching FMP instances\n", HandleCount));
+
+  switch (HandleCount) {
+    case 0:
+      //
+      // Install FMP protocol onto a new handle.
+      //
+      DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install FMP onto a new handle\n"));
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &mSystemFmpPrivate->Handle,
+                      &gEfiFirmwareManagementProtocolGuid,
+                      &mSystemFmpPrivate->Fmp,
+                      NULL
+                      );
+      break;
+    case 1:
+      //
+      // Install System FMP protocol onto handle with matching FMP Protocol
+      //
+      DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install System FMP onto matching FMP handle\n"));
+      mSystemFmpPrivate->Handle = HandleBuffer[0];
+      Status                    = gBS->InstallMultipleProtocolInterfaces (
+                                         &HandleBuffer[0],
+                                         &gSystemFmpProtocolGuid,
+                                         &mSystemFmpPrivate->Fmp,
+                                         NULL
+                                         );
+      break;
+    default:
+      //
+      // More than one matching handle is not expected.  Unload driver.
+      //
+      DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: More than one matching FMP handle.  Unload driver.\n"));
+      Status = EFI_DEVICE_ERROR;
+      break;
+  }
+
+  if (HandleBuffer != NULL) {
+    FreePool (HandleBuffer);
+  }
+
+  if (EFI_ERROR (Status)) {
+    FreePool (mSystemFmpPrivate);
+    mSystemFmpPrivate = NULL;
+  }
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
new file mode 100644
index 0000000000..6e990f7e4e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
@@ -0,0 +1,77 @@
+## @file
+#  System Firmware Update Dxe
+# Produce FMP instance to update system firmware.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SystemFirmwareUpdateDxe
+  MODULE_UNI_FILE                = SystemFirmwareUpdateDxe.uni
+  FILE_GUID                      = 0A2FBD15-1C25-407E-8915-60C5652BC2AA
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SystemFirmwareUpdateMainDxe
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources]
+  SystemFirmwareDxe.h
+  SystemFirmwareCommonDxe.c
+  SystemFirmwareUpdateDxe.c
+  ParseConfigProfile.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  SignedCapsulePkg/SignedCapsulePkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  HobLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  DxeServicesLib
+  EdkiiSystemCapsuleLib
+  PlatformFlashAccessLib
+  IniParsingLib
+  PrintLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid           ## CONSUMES
+  gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareFileGuid           ## CONSUMES
+  gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor    ## CONSUMES
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress                          ## CONSUMES
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize                                 ## CONSUMES
+  gPlatformPkgTokenSpaceGuid.PcdFlashAbImageSlotDefaultPriority               ## CONSUMES
+
+[Guids]
+  gOtaCapsuleUpdateGuid
+  gABSupportUpdateIshGuid
+
+[Protocols]
+  gEfiFirmwareManagementProtocolGuid     ## PRODUCES
+
+[Depex]
+  gEfiVariableArchProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  SystemFirmwareUpdateDxeExtra.uni
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
new file mode 100644
index 0000000000..e6bd18b249
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
@@ -0,0 +1,15 @@
+// /** @file
+// SystemFirmware FMP update driver.
+//
+// Produce FMP instance to update system firmware.
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "SystemFirmware FMP update driver."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Produce FMP instance to update system firmware."
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
new file mode 100644
index 0000000000..c549f017a4
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
@@ -0,0 +1,15 @@
+// /** @file
+// SystemFirmwareUpdateDxeExtra Localized Strings and Content
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"SystemFirmwareUpdate DXE Driver"
+
+
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114597): https://edk2.groups.io/g/devel/message/114597
Mute This Topic: https://groups.io/mt/103975474/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 22/32] AMD/VanGoghBoard: Check in Vtf0
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (20 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 21/32] AMD/VanGoghBoard: Check in SignedCapsule Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 23/32] AMD/VanGoghBoard: Check in AcpiPlatform Zhai, MingXin (Duke) via groups.io
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Ken Yao, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial Vtf0 module.
  This module includes all assembly code files of reset vector.

Signed-off-by: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../ResetVector/Vtf0/CommonMacros.inc         |  27 +++
 .../ResetVector/Vtf0/DebugDisabled.asm        |  21 ++
 .../ResetVector/Vtf0/Ia16/Init16.asm          |  51 +++++
 .../ResetVector/Vtf0/Ia16/Real16ToFlat32.asm  | 138 +++++++++++++
 .../ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm | 108 ++++++++++
 .../ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm  |  40 ++++
 .../ResetVector/Vtf0/Ia32/PageTables64.asm    |  25 +++
 .../Vtf0/Ia32/SearchForBfvBase.asm            |  84 ++++++++
 .../Vtf0/Ia32/SearchForSecEntry.asm           | 195 ++++++++++++++++++
 .../edk2/UefiCpuPkg/ResetVector/Vtf0/Main.asm | 127 ++++++++++++
 .../ResetVector/Vtf0/Port80Debug.asm          |  23 +++
 .../UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc |  20 ++
 .../ResetVector/Vtf0/ResetVector.uni          | Bin 0 -> 780 bytes
 .../ResetVector/Vtf0/ResetVectorExtra.uni     | Bin 0 -> 682 bytes
 .../ResetVector/Vtf0/SerialDebug.asm          | 127 ++++++++++++
 .../edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf |  37 ++++
 .../UefiCpuPkg/ResetVector/Vtf0/Vtf0.nasmb    |  67 ++++++
 .../ResetVector/Vtf0/X64/PageTables.asm       |  73 +++++++
 18 files changed, 1163 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/CommonMacros.inc
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/DebugDisabled.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/PageTables64.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForBfvBase.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Main.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Port80Debug.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/ResetVector.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/ResetVectorExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/SerialDebug.asm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.nasmb
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/X64/PageTables.asm

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/CommonMacros.inc b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/CommonMacros.inc
new file mode 100644
index 0000000000..5da472faaa
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/CommonMacros.inc
@@ -0,0 +1,27 @@
+;------------------------------------------------------------------------------
+; @file
+; Common macros used in the ResetVector VTF module.
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+%define ADDR16_OF(x) (0x10000 - fourGigabytes + x)
+%define ADDR_OF(x) (0x100000000 - fourGigabytes + x)
+%define ADDR_OF_MEM(x) (VIRTUAL4G - fourGigabytes + x)
+%define SMM_RESUME_SIGNATURE 0x55AABB66
+%macro  OneTimeCall 1
+    jmp     %1
+%1 %+ OneTimerCallReturn:
+%endmacro
+
+%macro  OneTimeCallRet 1
+    jmp     %1 %+ OneTimerCallReturn
+%endmacro
+
+StartOfResetVectorCode:
+
+%define ADDR_OF_START_OF_RESET_CODE ADDR_OF(StartOfResetVectorCode)
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/DebugDisabled.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/DebugDisabled.asm
new file mode 100644
index 0000000000..540206a1d0
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/DebugDisabled.asm
@@ -0,0 +1,21 @@
+;------------------------------------------------------------------------------
+; @file
+; Debug disabled
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS    16
+
+%macro  debugInitialize 0
+    ;
+    ; No initialization is required
+    ;
+%endmacro
+
+%macro  debugShowPostCode 1
+%endmacro
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
new file mode 100644
index 0000000000..36641c578b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Init16.asm
@@ -0,0 +1,51 @@
+;------------------------------------------------------------------------------
+; @file
+; 16-bit initialization code
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+
+BITS    16
+
+ALIGN   4
+SMMResumeInfo: ;; This offset can bie found as 0xFFFFFFF5 + word [0xFFFFFFF3] - 0x10(16)
+      DD ADDR_OF_MEM(GDT_BASE)        ; GDT base address
+      DW LINEAR_CODE_SEL              ; code segment
+      DW LINEAR_SEL                   ; data segment
+      DD ADDR_OF_MEM(Main32)          ; Offset of our 32 bit code
+      DD SMM_RESUME_SIGNATURE
+
+;
+; @param[out] DI    'BP' to indicate boot-strap processor
+;
+EarlyBspInitReal16:
+    mov     di, 'BP'
+    jmp     short Main16
+
+;
+; @param[out] DI    'AP' to indicate application processor
+;
+EarlyApInitReal16:
+    mov     di, 'AP'
+    jmp     short Main16
+
+;
+; Modified:  EAX
+;
+; @param[in]  EAX   Initial value of the EAX register (BIST: Built-in Self Test)
+; @param[out] ESP   Initial value of the EAX register (BIST: Built-in Self Test)
+;
+EarlyInit16:
+    ;
+    ; ESP -  Initial value of the EAX register (BIST: Built-in Self Test)
+    ;
+    mov     esp, eax
+
+    debugInitialize
+
+    OneTimeCallRet EarlyInit16
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
new file mode 100644
index 0000000000..f986761488
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
@@ -0,0 +1,138 @@
+;------------------------------------------------------------------------------
+; @file
+; Transition from 16 bit real mode into 32 bit flat protected mode
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+%define SEC_DEFAULT_CR0  0x40000023
+%define SEC_DEFAULT_CR4  0x640
+
+BITS    16
+
+;
+; Modified:  EAX, EBX
+;
+; @param[out]     DS       Selector allowing flat access to all addresses
+; @param[out]     ES       Selector allowing flat access to all addresses
+; @param[out]     FS       Selector allowing flat access to all addresses
+; @param[out]     GS       Selector allowing flat access to all addresses
+; @param[out]     SS       Selector allowing flat access to all addresses
+;
+TransitionFromReal16To32BitFlat:
+    movd    mm0, eax                    ;   ( BIST )
+
+    debugShowPostCode POSTCODE_16BIT_MODE
+
+    cli
+
+    mov     bx, ADDR16_OF(gdtrmem)
+
+o32 lgdt    [cs:bx]
+
+    mov     eax, SEC_DEFAULT_CR0
+    mov     cr0, eax
+
+    mov     edx, VIRTUAL4G
+    jmp     LINEAR_CODE_SEL:dword ADDR_OF_MEM(jumpTo32BitAndLandHere)
+
+BITS    32
+jumpTo32BitAndLandHere:
+
+    mov     eax, SEC_DEFAULT_CR4
+    mov     cr4, eax
+
+    debugShowPostCode POSTCODE_32BIT_MODE
+
+    mov     ax, LINEAR_SEL
+    mov     ds, ax
+    mov     es, ax
+    mov     fs, ax
+    mov     gs, ax
+    mov     ss, ax
+
+    OneTimeCallRet TransitionFromReal16To32BitFlat
+
+ALIGN   2
+
+gdtrmem:
+    dw      GDT_END - GDT_BASE - 1   ; GDT limit
+    dd      ADDR_OF_MEM(GDT_BASE)
+
+gdtr:
+    dw      GDT_END - GDT_BASE - 1   ; GDT limit
+    dd      ADDR_OF(GDT_BASE)
+
+ALIGN   16
+
+;
+; Macros for GDT entries
+;
+
+%define  PRESENT_FLAG(p) (p << 7)
+%define  DPL(dpl) (dpl << 5)
+%define  SYSTEM_FLAG(s) (s << 4)
+%define  DESC_TYPE(t) (t)
+
+; Type: data, expand-up, writable, accessed
+%define  DATA32_TYPE 3
+
+; Type: execute, readable, expand-up, accessed
+%define  CODE32_TYPE 0xb
+
+; Type: execute, readable, expand-up, accessed
+%define  CODE64_TYPE 0xb
+
+%define  GRANULARITY_FLAG(g) (g << 7)
+%define  DEFAULT_SIZE32(d) (d << 6)
+%define  CODE64_FLAG(l) (l << 5)
+%define  UPPER_LIMIT(l) (l)
+
+;
+; The Global Descriptor Table (GDT)
+;
+
+GDT_BASE:
+; null descriptor
+NULL_SEL            equ $-GDT_BASE
+    DW      0            ; limit 15:0
+    DW      0            ; base 15:0
+    DB      0            ; base 23:16
+    DB      0            ; sys flag, dpl, type
+    DB      0            ; limit 19:16, flags
+    DB      0            ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL          equ $-GDT_BASE
+    DW      0xffff       ; limit 15:0
+    DW      0            ; base 15:0
+    DB      0            ; base 23:16
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE)
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+    DB      0            ; base 31:24
+
+; linear code segment descriptor
+LINEAR_CODE_SEL     equ $-GDT_BASE
+    DW      0xffff       ; limit 15:0
+    DW      0            ; base 15:0
+    DB      0            ; base 23:16
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+    DB      0            ; base 31:24
+
+%ifdef ARCH_X64
+; linear code (64-bit) segment descriptor
+LINEAR_CODE64_SEL   equ $-GDT_BASE
+    DW      0xffff       ; limit 15:0
+    DW      0            ; base 15:0
+    DB      0            ; base 23:16
+    DB      PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE64_TYPE)
+    DB      GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(1)|UPPER_LIMIT(0xf)
+    DB      0            ; base 31:24
+%endif
+
+GDT_END:
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
new file mode 100644
index 0000000000..8234366b2a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
@@ -0,0 +1,108 @@
+;------------------------------------------------------------------------------
+; @file
+; First code executed by processor after resetting.
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS    16
+
+ALIGN   16
+
+;
+; Pad the image size to 4k when page tables are in VTF0
+;
+; If the VTF0 image has page tables built in, then we need to make
+; sure the end of VTF0 is 4k above where the page tables end.
+;
+; This is required so the page tables will be 4k aligned when VTF0 is
+; located just below 0x100000000 (4GB) in the firmware device.
+;
+%ifdef ALIGN_TOP_TO_4K_FOR_PAGING
+    TIMES (0x1000 - ($ - EndOfPageTables) - 0x50) DB 0
+%endif
+
+; 16 bytes reserved for Anti-rollback security level
+;  - 04 bytes: Security level
+;  - 12 bytes: Pad 0x00
+    DD AntiRollback_SecurityLevel
+    TIMES 12 DB 0
+
+;
+; 32 bytes reserved for BIOS version string and build date and time
+; Signature 4 bytes: BIVS
+; Pad0      1 byte,  00
+; Version   8 bytes, such as UMD9B18C
+; Pad1      1 byte,  00
+; Date      4 bytes, such as 20191118
+; Pad2      1 byte,  00
+; Time      3 bytes, such as 113028
+; Pad3      10 byte,  00
+;
+
+BiosVersionDateTimeSignature:
+    DB 'B', 'I', 'V', 'S'
+
+Pad0:
+    DB 0
+
+Version:
+    TIMES 8 DB 0
+
+Pad1:
+    DB 0
+
+Date:
+    TIMES 4 DB 0
+
+Pad2:
+    DB 0
+
+DateTime:
+    TIMES 7 DB 0
+
+Pad3:
+    TIMES 10 DB 0
+
+applicationProcessorEntryPoint:
+;
+; Application Processors entry point
+;
+; GenFv generates code aligned on a 4k boundary which will jump to this
+; location.  (0xffffffe0)  This allows the Local APIC Startup IPI to be
+; used to wake up the application processors.
+;
+    jmp     EarlyApInitReal16
+
+ALIGN   8
+
+    DD      0
+
+;
+; The VTF signature
+;
+; VTF-0 means that the VTF (Volume Top File) code does not require
+; any fixups.
+;
+vtfSignature:
+    DB      'V', 'T', 'F', 0
+
+ALIGN   16
+
+resetVector:
+;
+; Reset Vector
+;
+; This is where the processor will begin execution
+;
+    nop
+    nop
+    jmp   near  EarlyBspInitReal16
+
+ALIGN   16
+
+fourGigabytes:
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm
new file mode 100644
index 0000000000..121046fbaf
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/Flat32ToFlat64.asm
@@ -0,0 +1,40 @@
+;------------------------------------------------------------------------------
+; @file
+; Transition from 32 bit flat protected mode into 64 bit flat protected mode
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS    32
+
+;
+; Modified:  EAX
+;
+Transition32FlatTo64Flat:
+
+    OneTimeCall SetCr3ForPageTables64
+
+    mov     eax, cr4
+    bts     eax, 5                      ; enable PAE
+    mov     cr4, eax
+
+    mov     ecx, 0xc0000080
+    rdmsr
+    bts     eax, 8                      ; set LME
+    wrmsr
+
+    mov     eax, cr0
+    bts     eax, 31                     ; set PG
+    mov     cr0, eax                    ; enable paging
+
+    jmp     LINEAR_CODE64_SEL:ADDR_OF(jumpTo64BitAndLandHere)
+BITS    64
+jumpTo64BitAndLandHere:
+
+    debugShowPostCode POSTCODE_64BIT_MODE
+
+    OneTimeCallRet Transition32FlatTo64Flat
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/PageTables64.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/PageTables64.asm
new file mode 100644
index 0000000000..14baa6e987
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/PageTables64.asm
@@ -0,0 +1,25 @@
+;------------------------------------------------------------------------------
+; @file
+; Sets the CR3 register for 64-bit paging
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS    32
+
+;
+; Modified:  EAX
+;
+SetCr3ForPageTables64:
+
+    ;
+    ; These pages are built into the ROM image in X64/PageTables.asm
+    ;
+    mov     eax, ADDR_OF(TopLevelPageDirectory)
+    mov     cr3, eax
+
+    OneTimeCallRet SetCr3ForPageTables64
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForBfvBase.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForBfvBase.asm
new file mode 100644
index 0000000000..533004be7e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForBfvBase.asm
@@ -0,0 +1,84 @@
+;------------------------------------------------------------------------------
+; @file
+; Search for the Boot Firmware Volume (BFV) base address
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+;#define EFI_FIRMWARE_FILE_SYSTEM2_GUID \
+;  { 0x8c8ce578, 0x8a3d, 0x4f1c, { 0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 } }
+%define FFS_GUID_DWORD0 0x8c8ce578
+%define FFS_GUID_DWORD1 0x4f1c8a3d
+%define FFS_GUID_DWORD2 0x61893599
+%define FFS_GUID_DWORD3 0xd32dc385
+
+BITS    32
+
+;
+; Modified:  EAX, EBX
+; Preserved: EDI, ESP
+;
+; @param[out]  EBP  Address of Boot Firmware Volume (BFV)
+;
+Flat32SearchForBfvBase:
+
+    mov     eax, edx ; edx maps 4G for SOC 15 or 0xA000000 for SOC 17
+    mov     esi, eax
+    sub     esi, 0x1000000
+searchingForBfvHeaderLoop:
+    ;
+    ; We check for a firmware volume at every 4KB address in the top 16MB
+    ; just below 4GB.  (Addresses at 0xffHHH000 where H is any hex digit.)
+    ;
+    sub     eax, 0x1000
+    cmp     eax, esi
+    jb      searchedForBfvHeaderButNotFound
+
+    ;
+    ; Check FFS GUID
+    ;
+    cmp     dword [eax + 0x10], FFS_GUID_DWORD0
+    jne     searchingForBfvHeaderLoop
+    cmp     dword [eax + 0x14], FFS_GUID_DWORD1
+    jne     searchingForBfvHeaderLoop
+    cmp     dword [eax + 0x18], FFS_GUID_DWORD2
+    jne     searchingForBfvHeaderLoop
+    cmp     dword [eax + 0x1c], FFS_GUID_DWORD3
+    jne     searchingForBfvHeaderLoop
+
+    ;
+    ; Check FV Length
+    ;
+    cmp     dword [eax + 0x24], 0
+    jne     searchingForBfvHeaderLoop
+    mov     ebx, eax
+    add     ebx, dword [eax + 0x20]
+    cmp     ebx, edx
+    jnz     searchingForBfvHeaderLoop
+
+    jmp     searchedForBfvHeaderAndItWasFound
+
+searchedForBfvHeaderButNotFound:
+    ;
+    ; Hang if the SEC entry point was not found
+    ;
+    debugShowPostCode POSTCODE_BFV_NOT_FOUND
+
+    ;
+    ; 0xbfbfbfbf in the EAX & EBP registers helps signal what failed
+    ; for debugging purposes.
+    ;
+    mov     eax, 0xBFBFBFBF
+    mov     ebp, eax
+    jmp     $
+
+searchedForBfvHeaderAndItWasFound:
+    mov     ebp, eax
+
+    debugShowPostCode POSTCODE_BFV_FOUND
+
+    OneTimeCallRet Flat32SearchForBfvBase
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm
new file mode 100644
index 0000000000..5bc83f39e5
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Ia32/SearchForSecEntry.asm
@@ -0,0 +1,195 @@
+;------------------------------------------------------------------------------
+; @file
+; Search for the SEC Core entry point
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS    32
+
+%define EFI_FV_FILETYPE_SECURITY_CORE         0x03
+
+;
+; Modified:  EAX, EBX, ECX, EDX
+; Preserved: EDI, EBP, ESP
+;
+; @param[in]   EBP  Address of Boot Firmware Volume (BFV)
+; @param[out]  ESI  SEC Core Entry Point Address
+;
+Flat32SearchForSecEntryPoint:
+
+    ;
+    ; Initialize EBP and ESI to 0
+    ;
+    xor     ebx, ebx
+    mov     esi, ebx
+
+    ;
+    ; Pass over the BFV header
+    ;
+    mov     eax, ebp
+    mov     bx, [ebp + 0x30]
+    add     eax, ebx
+    jc      secEntryPointWasNotFound
+
+    jmp     searchingForFfsFileHeaderLoop
+
+moveForwardWhileSearchingForFfsFileHeaderLoop:
+    ;
+    ; Make forward progress in the search
+    ;
+    inc     eax
+    jc      secEntryPointWasNotFound
+
+searchingForFfsFileHeaderLoop:
+    test    eax, eax
+    jz      secEntryPointWasNotFound
+
+    ;
+    ; Ensure 8 byte alignment
+    ;
+    add     eax, 7
+    jc      secEntryPointWasNotFound
+    and     al, 0xf8
+
+    ;
+    ; Look to see if there is an FFS file at eax
+    ;
+    mov     bl, [eax + 0x17]
+    test    bl, 0x20
+    jz      moveForwardWhileSearchingForFfsFileHeaderLoop
+    mov     ecx, [eax + 0x14]
+    and     ecx, 0x00ffffff
+    or      ecx, ecx
+    jz      moveForwardWhileSearchingForFfsFileHeaderLoop
+    add     ecx, eax
+    jz      jumpSinceWeFoundTheLastFfsFile
+    jc      moveForwardWhileSearchingForFfsFileHeaderLoop
+jumpSinceWeFoundTheLastFfsFile:
+
+    ;
+    ; There seems to be a valid file at eax
+    ;
+    cmp     byte [eax + 0x12], EFI_FV_FILETYPE_SECURITY_CORE ; Check File Type
+    jne     readyToTryFfsFileAtEcx
+
+fileTypeIsSecCore:
+    OneTimeCall GetEntryPointOfFfsFile
+    test    eax, eax
+    jnz     doneSeachingForSecEntryPoint
+
+readyToTryFfsFileAtEcx:
+    ;
+    ; Try the next FFS file at ECX
+    ;
+    mov     eax, ecx
+    jmp     searchingForFfsFileHeaderLoop
+
+secEntryPointWasNotFound:
+    xor     eax, eax
+
+doneSeachingForSecEntryPoint:
+    mov     esi, eax
+
+    test    esi, esi
+    jnz     secCoreEntryPointWasFound
+
+secCoreEntryPointWasNotFound:
+    ;
+    ; Hang if the SEC entry point was not found
+    ;
+    debugShowPostCode POSTCODE_SEC_NOT_FOUND
+    jz      $
+
+secCoreEntryPointWasFound:
+    debugShowPostCode POSTCODE_SEC_FOUND
+
+    OneTimeCallRet Flat32SearchForSecEntryPoint
+
+%define EFI_SECTION_PE32                  0x10
+%define EFI_SECTION_TE                    0x12
+
+;
+; Input:
+;   EAX - Start of FFS file
+;   ECX - End of FFS file
+;
+; Output:
+;   EAX - Entry point of PE32 (or 0 if not found)
+;
+; Modified:
+;   EBX
+;
+GetEntryPointOfFfsFile:
+    test    eax, eax
+    jz      getEntryPointOfFfsFileErrorReturn
+    add     eax, 0x18       ; EAX = Start of section
+
+getEntryPointOfFfsFileLoopForSections:
+    cmp     eax, ecx
+    jae     getEntryPointOfFfsFileErrorReturn
+
+    cmp     byte [eax + 3], EFI_SECTION_PE32
+    je      getEntryPointOfFfsFileFoundPe32Section
+
+    cmp     byte [eax + 3], EFI_SECTION_TE
+    je      getEntryPointOfFfsFileFoundTeSection
+
+    ;
+    ; The section type was not PE32 or TE, so move to next section
+    ;
+    mov     ebx, dword [eax]
+    and     ebx, 0x00ffffff
+    add     eax, ebx
+    jc      getEntryPointOfFfsFileErrorReturn
+
+    ;
+    ; Ensure that FFS section is 32-bit aligned
+    ;
+    add     eax, 3
+    jc      getEntryPointOfFfsFileErrorReturn
+    and     al, 0xfc
+    jmp     getEntryPointOfFfsFileLoopForSections
+
+getEntryPointOfFfsFileFoundPe32Section:
+    add     eax, 4       ; EAX = Start of PE32 image
+
+    cmp     word [eax], 'MZ'
+    jne     getEntryPointOfFfsFileErrorReturn
+    movzx   ebx, word [eax + 0x3c]
+    add     ebx, eax
+
+    ; if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)
+    cmp     dword [ebx], `PE\x00\x00`
+    jne     getEntryPointOfFfsFileErrorReturn
+
+    ; *EntryPoint = (VOID *)((UINTN)Pe32Data +
+    ;   (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
+    add     eax, [ebx + 0x4 + 0x14 + 0x10]
+    jmp     getEntryPointOfFfsFileReturn
+
+getEntryPointOfFfsFileFoundTeSection:
+    add     eax, 4       ; EAX = Start of TE image
+    mov     ebx, eax
+
+    ; if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE)
+    cmp     word [ebx], 'VZ'
+    jne     getEntryPointOfFfsFileErrorReturn
+    ; *EntryPoint = (VOID *)((UINTN)Pe32Data +
+    ;   (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) +
+    ;   sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
+    add     eax, [ebx + 0x8]
+    add     eax, 0x28
+    movzx   ebx, word [ebx + 0x6]
+    sub     eax, ebx
+    jmp     getEntryPointOfFfsFileReturn
+
+getEntryPointOfFfsFileErrorReturn:
+    mov     eax, 0
+
+getEntryPointOfFfsFileReturn:
+    OneTimeCallRet GetEntryPointOfFfsFile
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Main.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Main.asm
new file mode 100644
index 0000000000..08b6076bb8
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Main.asm
@@ -0,0 +1,127 @@
+;------------------------------------------------------------------------------
+; @file
+; Main routine of the pre-SEC code up through the jump into SEC
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+
+BITS    16
+
+;
+; Modified:  EBX, ECX, EDX, EBP
+;
+; @param[in,out]  RAX/EAX  Initial value of the EAX register
+;                          (BIST: Built-in Self Test)
+; @param[in,out]  DI       'BP': boot-strap processor, or
+;                          'AP': application processor
+; @param[out]     RBP/EBP  Address of Boot Firmware Volume (BFV)
+; @param[out]     DS       Selector allowing flat access to all addresses
+; @param[out]     ES       Selector allowing flat access to all addresses
+; @param[out]     FS       Selector allowing flat access to all addresses
+; @param[out]     GS       Selector allowing flat access to all addresses
+; @param[out]     SS       Selector allowing flat access to all addresses
+;
+; @return         None  This routine jumps to SEC and does not return
+;
+Main16:
+    OneTimeCall EarlyInit16
+
+    ;
+    ; Transition the processor from 16-bit real mode to 32-bit flat mode
+    ;
+    OneTimeCall TransitionFromReal16To32BitFlat
+
+BITS    32
+    jmp     Not_S3Resume
+
+Main32:
+    cmp     edx, SMM_RESUME_SIGNATURE
+    jne     Not_S3Resume
+
+    mov     ebx, esp
+    push    ebx
+
+    push    eax
+    push    edx
+
+    mov     eax, esi
+    push    eax
+
+    mov     eax, edi
+    push    eax
+
+    mov     edi, SMM_RESUME_SIGNATURE
+    mov     edx, VIRTUAL4G
+
+Not_S3Resume:
+    ;
+    ; Search for the Boot Firmware Volume (BFV)
+    ;
+    OneTimeCall Flat32SearchForBfvBase
+
+    ;
+    ; EBP - Start of BFV
+    ;
+
+    ;
+    ; Search for the SEC entry point
+    ;
+    OneTimeCall Flat32SearchForSecEntryPoint
+
+    ;
+    ; ESI - SEC Core entry point
+    ; EBP - Start of BFV
+    ;
+
+%ifdef ARCH_IA32
+
+    ;
+    ; Restore initial EAX value into the EAX register
+    ;
+    mov     eax, esp
+
+    ;
+    ; Jump to the 32-bit SEC entry point
+    ;
+    jmp     esi
+
+%else
+
+    ;
+    ; Transition the processor from 32-bit flat mode to 64-bit flat mode
+    ;
+    OneTimeCall Transition32FlatTo64Flat
+
+BITS    64
+
+    ;
+    ; Some values were calculated in 32-bit mode.  Make sure the upper
+    ; 32-bits of 64-bit registers are zero for these values.
+    ;
+    mov     rax, 0x00000000ffffffff
+    and     rsi, rax
+    and     rbp, rax
+    and     rsp, rax
+
+    ;
+    ; RSI - SEC Core entry point
+    ; RBP - Start of BFV
+    ;
+
+    ;
+    ; Restore initial EAX value into the RAX register
+    ;
+    mov     rax, rsp
+
+    ;
+    ; Jump to the 64-bit SEC entry point
+    ;
+    jmp     rsi
+
+%endif
+
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Port80Debug.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Port80Debug.asm
new file mode 100644
index 0000000000..7cb83244df
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Port80Debug.asm
@@ -0,0 +1,23 @@
+;------------------------------------------------------------------------------
+; @file
+; Port 0x80 debug support macros
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS    16
+
+%macro  debugInitialize 0
+    ;
+    ; No initialization is required
+    ;
+%endmacro
+
+%macro  debugShowPostCode 1
+    mov     al, %1
+    out     0x80, al
+%endmacro
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc
new file mode 100644
index 0000000000..326c8621d7
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/PostCodes.inc
@@ -0,0 +1,20 @@
+;------------------------------------------------------------------------------
+; @file
+; Definitions of POST CODES for the reset vector module
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+%define POSTCODE_16BIT_MODE     0x16
+%define POSTCODE_32BIT_MODE     0x32
+%define POSTCODE_64BIT_MODE     0x64
+
+%define POSTCODE_BFV_NOT_FOUND  0xb0
+%define POSTCODE_BFV_FOUND      0xb1
+
+%define POSTCODE_SEC_NOT_FOUND  0xf0
+%define POSTCODE_SEC_FOUND      0xf1
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/ResetVector.uni b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/ResetVector.uni
new file mode 100644
index 0000000000000000000000000000000000000000..b05945351150015ad85feecf680a5dc2cb41f894
GIT binary patch
literal 780
zcmbu7O-sW-5Qg8gzaq3371LBH9z?{n^-%C5G*!GwNn;I!RMHRd&#TXDlH#E~s4Uyg
z&d$vH%xu0s0|oNf$1G3RdR3-esSfbj%@}*hUSU7+pI|Li*7r@+0N=Yl@MoIq%|#z-
zpd+%*)MfXuLd~?%R0UO1Y)^N@CuA+Khxj(`Y>Fp%MlQ1BGIOZBAN7~+RI!!hS-p-f
z)ra_MOTU{d*>ZJtP92|Zl&4TOx+^N0qE#sA&3>o!m0=YqSvP-SY9<ydqT^?@Z|j~5
zH)o%&XJ{8r%U&Zz`2xMZVlsS4eW-G1)^$eY$f}&GexqWq8ZZr8ZK79hf(38nQEkGk
zUU-8C>OR78!zpw+b`zp9A#UGlI|i$@Mt=^c=eT`p#n`RA-%jfnJVU5rNXE=1f@cKn
K{Z6L;@_YjtHFW_1

literal 0
HcmV?d00001

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/ResetVectorExtra.uni b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/ResetVectorExtra.uni
new file mode 100644
index 0000000000000000000000000000000000000000..332232d2a2aa0cb9abd8e87dd1269917382e2af5
GIT binary patch
literal 682
zcmbu7OH0E*6ot<^zhbBx71L;OB_i4;3&Ch<s<<m5sj*N~iMF6WUj6R$p^NNfn7McE
z^PIW!{S_&aV;{1dF7>3D=9((NW}XrH8~a@koCR{B2Kx=NP)_VjpLj}a8Qz9_t%@9n
zxAyh{u{FM_Ki8GF_09LH51&`*nJA}y4RnC)>6m?rc14|)uUBk(rSvJtTHuYbt^D1v
z9$~qrQ=zWUoP*K*sc*;{GK^J2o?-9mTz$A+?0C21Dt5R|z_smU%&dpyG_bKVhsg}B
z{s)Tf8)X{8@lheKZmjJc4SfjD(%-C?P0kpdfuzqYV*EY!0BpIIn~b4H);0<I0TKKI
z?GgJsNt^4Kx0!%qq&v<8Ii`1lXQC8atb4E}+-{jwisq<deeEwSkrmjS#~Kowp?9d#
R{<mIuw~{RThaHb7&<}~YY~la_

literal 0
HcmV?d00001

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/SerialDebug.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/SerialDebug.asm
new file mode 100644
index 0000000000..eec19a20e7
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/SerialDebug.asm
@@ -0,0 +1,127 @@
+;------------------------------------------------------------------------------
+; @file
+; Serial port debug support macros
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+;//---------------------------------------------
+;// UART Register Offsets
+;//---------------------------------------------
+%define BAUD_LOW_OFFSET         0x00
+%define BAUD_HIGH_OFFSET        0x01
+%define IER_OFFSET              0x01
+%define LCR_SHADOW_OFFSET       0x01
+%define FCR_SHADOW_OFFSET       0x02
+%define IR_CONTROL_OFFSET       0x02
+%define FCR_OFFSET              0x02
+%define EIR_OFFSET              0x02
+%define BSR_OFFSET              0x03
+%define LCR_OFFSET              0x03
+%define MCR_OFFSET              0x04
+%define LSR_OFFSET              0x05
+%define MSR_OFFSET              0x06
+
+;//---------------------------------------------
+;// UART Register Bit Defines
+;//---------------------------------------------
+%define LSR_TXRDY               0x20
+%define LSR_RXDA                0x01
+%define DLAB                    0x01
+
+; UINT16  gComBase = 0x3f8;
+; UINTN   gBps = 115200;
+; UINT8   gData = 8;
+; UINT8   gStop = 1;
+; UINT8   gParity = 0;
+; UINT8   gBreakSet = 0;
+
+%define DEFAULT_COM_BASE 0x3f8
+%define DEFAULT_BPS 115200
+%define DEFAULT_DATA 8
+%define DEFAULT_STOP 1
+%define DEFAULT_PARITY 0
+%define DEFAULT_BREAK_SET 0
+
+%define SERIAL_DEFAULT_LCR ( \
+     (DEFAULT_BREAK_SET << 6) | \
+     (DEFAULT_PARITY << 3) | \
+     (DEFAULT_STOP << 2) | \
+     (DEFAULT_DATA - 5) \
+    )
+
+%define SERIAL_PORT_IO_BASE_ADDRESS DEFAULT_COM_BASE
+
+%macro  inFromSerialPort 1
+    mov     dx, (SERIAL_PORT_IO_BASE_ADDRESS + %1)
+    in      al, dx
+%endmacro
+
+%macro  waitForSerialTxReady 0
+
+%%waitingForTx:
+    inFromSerialPort LSR_OFFSET
+    test    al, LSR_TXRDY
+    jz      %%waitingForTx
+
+%endmacro
+
+%macro  outToSerialPort 2
+    mov     dx, (SERIAL_PORT_IO_BASE_ADDRESS + %1)
+    mov     al, %2
+    out     dx, al
+%endmacro
+
+%macro  debugShowCharacter 1
+    waitForSerialTxReady
+    outToSerialPort 0, %1
+%endmacro
+
+%macro  debugShowHexDigit 1
+  %if (%1 < 0xa)
+    debugShowCharacter BYTE ('0' + (%1))
+  %else
+    debugShowCharacter BYTE ('a' + ((%1) - 0xa))
+  %endif
+%endmacro
+
+%macro  debugNewline 0
+    debugShowCharacter `\r`
+    debugShowCharacter `\n`
+%endmacro
+
+%macro  debugShowPostCode 1
+    debugShowHexDigit (((%1) >> 4) & 0xf)
+    debugShowHexDigit ((%1) & 0xf)
+    debugNewline
+%endmacro
+
+BITS    16
+
+%macro  debugInitialize 0
+  jmp  real16InitDebug
+real16InitDebugReturn:
+%endmacro
+
+real16InitDebug:
+    ;
+    ; Set communications format
+    ;
+    outToSerialPort LCR_OFFSET, ((DLAB << 7) | SERIAL_DEFAULT_LCR)
+
+    ;
+    ; Configure baud rate
+    ;
+    outToSerialPort BAUD_HIGH_OFFSET, ((115200 / DEFAULT_BPS) >> 8)
+    outToSerialPort BAUD_LOW_OFFSET, ((115200 / DEFAULT_BPS) & 0xff)
+
+    ;
+    ; Switch back to bank 0
+    ;
+    outToSerialPort LCR_OFFSET, SERIAL_DEFAULT_LCR
+
+    jmp     real16InitDebugReturn
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf
new file mode 100644
index 0000000000..6271e7ac7f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf
@@ -0,0 +1,37 @@
+## @file
+#  Reset Vector
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = ResetVector
+  FILE_GUID                      = 1BA0062E-C779-4582-8566-336AE8F78F09
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.1
+  MODULE_UNI_FILE                = ResetVector.uni
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  Vtf0.nasmb
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[Pcd]
+  gPlatformPkgTokenSpaceGuid.PcdMemoryFvRecoveryBase
+  gPlatformPkgTokenSpaceGuid.PcdFlashFvRecoverySize
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  ResetVectorExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.nasmb b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.nasmb
new file mode 100644
index 0000000000..5eaa95148f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/Vtf0.nasmb
@@ -0,0 +1,67 @@
+;------------------------------------------------------------------------------
+; @file
+; This file includes all other code files to assemble the reset vector code
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+;
+; If neither ARCH_IA32 nor ARCH_X64 are defined, then try to include
+; Base.h to use the C pre-processor to determine the architecture.
+;
+%ifndef ARCH_IA32
+  %ifndef ARCH_X64
+    #include <Base.h>
+    #if defined (MDE_CPU_IA32)
+      %define ARCH_IA32
+    #elif defined (MDE_CPU_X64)
+      %define ARCH_X64
+    #endif
+  %endif
+%endif
+  #include <AutoGen.h>
+  %define VIRTUAL4G (FixedPcdGet32 (PcdMemoryFvRecoveryBase)+FixedPcdGet32 (PcdFlashFvRecoverySize))
+  %define AntiRollback_SecurityLevel (0)
+%ifdef ARCH_IA32
+  %ifdef ARCH_X64
+    %error "Only one of ARCH_IA32 or ARCH_X64 can be defined."
+  %endif
+%elifdef ARCH_X64
+%else
+  %error "Either ARCH_IA32 or ARCH_X64 must be defined."
+%endif
+
+%include "CommonMacros.inc"
+
+%include "PostCodes.inc"
+
+%ifdef ARCH_X64
+%include "X64/PageTables.asm"
+%endif
+
+%ifdef DEBUG_PORT80
+  %include "Port80Debug.asm"
+%elifdef DEBUG_SERIAL
+  %include "SerialDebug.asm"
+%else
+  %include "DebugDisabled.asm"
+%endif
+
+%include "Ia32/SearchForBfvBase.asm"
+%include "Ia32/SearchForSecEntry.asm"
+
+%ifdef ARCH_X64
+%include "Ia32/Flat32ToFlat64.asm"
+%include "Ia32/PageTables64.asm"
+%endif
+
+%include "Ia16/Real16ToFlat32.asm"
+%include "Ia16/Init16.asm"
+
+%include "Main.asm"
+
+%include "Ia16/ResetVectorVtf0.asm"
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/X64/PageTables.asm b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/X64/PageTables.asm
new file mode 100644
index 0000000000..0f085cfa27
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/ResetVector/Vtf0/X64/PageTables.asm
@@ -0,0 +1,73 @@
+;------------------------------------------------------------------------------
+; @file
+; Emits Page Tables for 1:1 mapping of the addresses 0 - 0x100000000 (4GB)
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS    64
+
+%define ALIGN_TOP_TO_4K_FOR_PAGING
+
+%define PAGE_PRESENT            0x01
+%define PAGE_READ_WRITE         0x02
+%define PAGE_USER_SUPERVISOR    0x04
+%define PAGE_WRITE_THROUGH      0x08
+%define PAGE_CACHE_DISABLE     0x010
+%define PAGE_ACCESSED          0x020
+%define PAGE_DIRTY             0x040
+%define PAGE_PAT               0x080
+%define PAGE_GLOBAL           0x0100
+%define PAGE_2M_MBO            0x080
+%define PAGE_2M_PAT          0x01000
+
+%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \
+                          PAGE_ACCESSED + \
+                          PAGE_DIRTY + \
+                          PAGE_READ_WRITE + \
+                          PAGE_PRESENT)
+
+%define PAGE_PDP_ATTR (PAGE_ACCESSED + \
+                       PAGE_READ_WRITE + \
+                       PAGE_PRESENT)
+
+%define PGTBLS_OFFSET(x) ((x) - TopLevelPageDirectory)
+%define PGTBLS_ADDR(x) (ADDR_OF(TopLevelPageDirectory) + (x))
+
+%define PDP(offset) (ADDR_OF(TopLevelPageDirectory) + (offset) + \
+                     PAGE_PDP_ATTR)
+%define PTE_2MB(x) ((x << 21) + PAGE_2M_PDE_ATTR)
+
+TopLevelPageDirectory:
+
+    ;
+    ; Top level Page Directory Pointers (1 * 512GB entry)
+    ;
+    DQ      PDP(0x1000)
+
+
+    ;
+    ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
+    ;
+    TIMES 0x1000-PGTBLS_OFFSET($) DB 0
+
+    DQ      PDP(0x2000)
+    DQ      PDP(0x3000)
+    DQ      PDP(0x4000)
+    DQ      PDP(0x5000)
+
+    ;
+    ; Page Table Entries (2048 * 2MB entries => 4GB)
+    ;
+    TIMES 0x2000-PGTBLS_OFFSET($) DB 0
+
+%assign i 0
+%rep    0x800
+    DQ      PTE_2MB(i)
+    %assign i i+1
+%endrep
+
+EndOfPageTables:
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114598): https://edk2.groups.io/g/devel/message/114598
Mute This Topic: https://groups.io/mt/103975477/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 23/32] AMD/VanGoghBoard: Check in AcpiPlatform
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (21 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 22/32] AMD/VanGoghBoard: Check in Vtf0 Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 24/32] AMD/VanGoghBoard: Check in FchSpi module Zhai, MingXin (Duke) via groups.io
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Ken Yao, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial Acpi platform dxe drivers. Use firmware volume protocol
  to update global NVS area for ASL and SMM init code.

Signed-off-by: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Universal/AcpiPlatformDxe/AcpiPlatform.c  | 336 ++++++++++++++++++
 .../AcpiPlatformDxe/AcpiPlatform.uni          |  15 +
 .../AcpiPlatformDxe/AcpiPlatformDxe.inf       |  59 +++
 .../AcpiPlatformDxe/AcpiPlatformExtra.uni     |  13 +
 .../AcpiPlatformDxe/AcpiPlatformHooks.c       | 152 ++++++++
 .../AcpiPlatformDxe/AcpiPlatformHooks.h       |  48 +++
 6 files changed, 623 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformExtra.uni
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.h

diff --git a/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.c b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.c
new file mode 100644
index 0000000000..73a022594e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,336 @@
+/** @file
+  Sample ACPI Platform Driver
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/FirmwareVolume2.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/Acpi.h>
+
+#include "AcpiPlatformHooks.h"
+#include <Protocol/GlobalNvsArea.h>
+
+EFI_GLOBAL_NVS_AREA_PROTOCOL  mGlobalNvsArea;
+
+/**
+  Locate the first instance of a protocol.  If the protocol requested is an
+  FV protocol, then it will return the first FV that contains the ACPI table
+  storage file.
+
+  @param  Instance      Return pointer to the first instance of the protocol
+
+  @return EFI_SUCCESS           The function completed successfully.
+  @return EFI_NOT_FOUND         The protocol could not be located.
+  @return EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.
+
+**/
+EFI_STATUS
+LocateFvInstanceWithTables (
+  OUT EFI_FIRMWARE_VOLUME2_PROTOCOL  **Instance
+  )
+{
+  EFI_STATUS                     Status;
+  EFI_HANDLE                     *HandleBuffer;
+  UINTN                          NumberOfHandles;
+  EFI_FV_FILETYPE                FileType;
+  UINT32                         FvStatus;
+  EFI_FV_FILE_ATTRIBUTES         Attributes;
+  UINTN                          Size;
+  UINTN                          Index;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL  *FvInstance;
+
+  FvStatus = 0;
+
+  //
+  // Locate protocol.
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiFirmwareVolume2ProtocolGuid,
+                  NULL,
+                  &NumberOfHandles,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    //
+    // Defined errors at this time are not found and out of resources.
+    //
+    return Status;
+  }
+
+  //
+  // Looking for FV with ACPI storage file
+  //
+
+  for (Index = 0; Index < NumberOfHandles; Index++) {
+    //
+    // Get the protocol on this handle
+    // This should not fail because of LocateHandleBuffer
+    //
+    Status = gBS->HandleProtocol (
+                    HandleBuffer[Index],
+                    &gEfiFirmwareVolume2ProtocolGuid,
+                    (VOID **)&FvInstance
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // See if it has the ACPI storage file
+    //
+    Status = FvInstance->ReadFile (
+                           FvInstance,
+                           (EFI_GUID *)PcdGetPtr (PcdAcpiTableStorageFile),
+                           NULL,
+                           &Size,
+                           &FileType,
+                           &Attributes,
+                           &FvStatus
+                           );
+
+    //
+    // If we found it, then we are done
+    //
+    if (Status == EFI_SUCCESS) {
+      *Instance = FvInstance;
+      break;
+    }
+  }
+
+  //
+  // Our exit status is determined by the success of the previous operations
+  // If the protocol was found, Instance already points to it.
+  //
+
+  //
+  // Free any allocated buffers
+  //
+  gBS->FreePool (HandleBuffer);
+
+  return Status;
+}
+
+/**
+  This function calculates and updates an UINT8 checksum.
+
+  @param  Buffer          Pointer to buffer to checksum
+  @param  Size            Number of bytes to checksum
+
+**/
+VOID
+AcpiPlatformChecksum (
+  IN UINT8  *Buffer,
+  IN UINTN  Size
+  )
+{
+  UINTN  ChecksumOffset;
+
+  ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
+
+  //
+  // Set checksum to 0 first
+  //
+  Buffer[ChecksumOffset] = 0;
+
+  //
+  // Update checksum value
+  //
+  Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);
+}
+
+/**
+  This function will update any runtime platform specific information.
+  This currently includes:
+    Setting OEM table values, ID, table ID, creator ID and creator revision.
+    Enabling the proper processor entries in the APIC tables.
+
+  @param[in]  Table       The table to update.
+
+  @retval  EFI_SUCCESS    The function completed successfully.
+
+**/
+EFI_STATUS
+PlatformUpdateTables (
+  IN OUT EFI_ACPI_COMMON_HEADER  *Table
+  )
+{
+  switch (Table->Signature) {
+    case EFI_ACPI_5_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
+      //
+      // Patch the memory resource.
+      //
+      PatchDsdtTable ((EFI_ACPI_DESCRIPTION_HEADER *)Table);
+      break;
+
+    case EFI_ACPI_5_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
+      PatchMadtTable ((EFI_ACPI_DESCRIPTION_HEADER *)Table);
+      break;
+
+    default:
+      break;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Entrypoint of Acpi Platform driver.
+
+  @param  ImageHandle
+  @param  SystemTable
+
+  @return EFI_SUCCESS
+  @return EFI_LOAD_ERROR
+  @return EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+AcpiPlatformEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                     Status;
+  EFI_STATUS                     AcpiStatus;
+  EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL  *FwVol;
+  INTN                           Instance;
+  EFI_ACPI_COMMON_HEADER         *CurrentTable;
+  UINTN                          TableHandle;
+  UINT32                         FvStatus;
+  UINTN                          TableSize;
+  UINTN                          Size;
+  EFI_HANDLE                     Handle;
+
+  Instance     = 0;
+  CurrentTable = NULL;
+  TableHandle  = 0;
+
+  //
+  // Find the AcpiTable protocol
+  //
+  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
+  if (EFI_ERROR (Status)) {
+    return EFI_ABORTED;
+  }
+
+  //
+  // Allocate and initialize the NVS area for SMM and ASL communication.
+  //
+  Status = gBS->AllocatePool (
+                  EfiACPIMemoryNVS,
+                  sizeof (EFI_GLOBAL_NVS_AREA),
+                  (void **)&mGlobalNvsArea.Area
+                  );
+  ASSERT_EFI_ERROR (Status);
+  gBS->SetMem (
+         mGlobalNvsArea.Area,
+         sizeof (EFI_GLOBAL_NVS_AREA),
+         0
+         );
+  DEBUG ((DEBUG_INFO, "mGlobalNvsArea.Area is at 0x%X\n", mGlobalNvsArea.Area));
+
+  //
+  // Update global NVS area for ASL and SMM init code to use.
+  //
+  mGlobalNvsArea.Area->PcieBaseAddress = (UINT32)PcdGet64 (PcdPciExpressBaseAddress);
+  mGlobalNvsArea.Area->PcieBaseLimit   = (UINT32)(PcdGet64 (PcdPciExpressBaseAddress) + (PcdGet32 (PcdPciExpressSize) - 1));
+
+  if (FeaturePcdGet (PcdNbIoApicSupport)) {
+    mGlobalNvsArea.Area->NbIoApic = TRUE;
+  } else {
+    mGlobalNvsArea.Area->NbIoApic = FALSE;
+  }
+
+  mGlobalNvsArea.Area->TopOfMem = (UINT32)AsmReadMsr64 (0xC001001A);
+
+  Handle = NULL;
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Handle,
+                  &gEfiGlobalNvsAreaProtocolGuid,
+                  &mGlobalNvsArea,
+                  NULL
+                  );
+
+  //
+  // Locate the firmware volume protocol
+  //
+  Status = LocateFvInstanceWithTables (&FwVol);
+  if (EFI_ERROR (Status)) {
+    return EFI_ABORTED;
+  }
+
+  //
+  // Read tables from the storage file.
+  //
+  while (Status == EFI_SUCCESS) {
+    Status = FwVol->ReadSection (
+                      FwVol,
+                      (EFI_GUID *)PcdGetPtr (PcdAcpiTableStorageFile),
+                      EFI_SECTION_RAW,
+                      Instance,
+                      (VOID **)&CurrentTable,
+                      &Size,
+                      &FvStatus
+                      );
+    if (!EFI_ERROR (Status)) {
+      AcpiStatus = PlatformUpdateTables (CurrentTable);
+      if (!EFI_ERROR (AcpiStatus)) {
+        //
+        // Add the table
+        //
+        TableHandle = 0;
+
+        TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *)CurrentTable)->Length;
+        ASSERT (Size >= TableSize);
+
+        //
+        // Checksum ACPI table
+        //
+        AcpiPlatformChecksum ((UINT8 *)CurrentTable, TableSize);
+
+        //
+        // Install ACPI table
+        //
+        Status = AcpiTable->InstallAcpiTable (
+                              AcpiTable,
+                              CurrentTable,
+                              TableSize,
+                              &TableHandle
+                              );
+      }
+
+      //
+      // Free memory allocated by ReadSection
+      //
+      gBS->FreePool (CurrentTable);
+
+      if (EFI_ERROR (Status)) {
+        return EFI_ABORTED;
+      }
+
+      //
+      // Increment the instance
+      //
+      Instance++;
+      CurrentTable = NULL;
+    }
+  }
+
+  //
+  // The driver does not require to be kept loaded.
+  //
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.uni b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.uni
new file mode 100644
index 0000000000..2001da520b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatform.uni
@@ -0,0 +1,15 @@
+// /** @file
+// Sample ACPI Platform Driver
+//
+// Sample ACPI Platform Driver
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "Sample ACPI Platform Driver"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Sample ACPI Platform Driver"
diff --git a/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformDxe.inf b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100644
index 0000000000..044218ff46
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,59 @@
+## @file
+#  Sample ACPI Platform Driver
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AcpiPlatform
+  MODULE_UNI_FILE                = AcpiPlatform.uni
+  FILE_GUID                      = 6A462E1D-7B1A-95BE-DCF1-241320F01646
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = AcpiPlatformEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  AcpiPlatform.c
+  AcpiPlatformHooks.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  UefiLib
+  DxeServicesLib
+  PcdLib
+  BaseMemoryLib
+  DebugLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid                     ## CONSUMES
+  gEfiGlobalNvsAreaProtocolGuid
+  gEfiMpServiceProtocolGuid
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile    ## CONSUMES
+  gPlatformPkgTokenSpaceGuid.PcdNbIoApicSupport
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gPlatformPkgTokenSpaceGuid.PcdPciExpressSize
+
+[Depex]
+  gEfiAcpiTableProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  AcpiPlatformExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformExtra.uni b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformExtra.uni
new file mode 100644
index 0000000000..04a89cf3fb
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformExtra.uni
@@ -0,0 +1,13 @@
+// /** @file
+// AcpiPlatform Localized Strings and Content
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"ACPI Platform Sample DXE Driver"
diff --git a/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.c b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.c
new file mode 100644
index 0000000000..7cf5845772
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.c
@@ -0,0 +1,152 @@
+/** @file
+  Sample ACPI Platform Driver
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// Statements that include other files.
+//
+#include "AcpiPlatformHooks.h"
+#include <Protocol/GlobalNvsArea.h>
+
+extern EFI_GLOBAL_NVS_AREA_PROTOCOL  mGlobalNvsArea;
+
+/**
+    Update the DSDT table.
+
+    @param   TableHeader   The table to be set.
+
+    @retval  EFI_SUCCESS   Update DSDT table sucessfully.
+
+**/
+EFI_STATUS
+PatchDsdtTable (
+  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader
+  )
+{
+  UINT8   *CurrPtr;
+  UINT8   *DsdtPointer;
+  UINT32  *Signature;
+  UINT8   *Operation;
+  UINT32  *Address;
+  UINT16  *Size;
+
+  //
+  // Loop through the ASL looking for values that we must fix up.
+  //
+  CurrPtr = (UINT8 *)TableHeader;
+  for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *)CurrPtr)->Length); DsdtPointer++) {
+    Signature = (UINT32 *)DsdtPointer;
+
+    switch (*Signature) {
+      //
+      // GNVS operation region.
+      //
+      case (SIGNATURE_32 ('G', 'N', 'V', 'S')):
+        //
+        // Conditional match.  For Region Objects, the Operator will always be the
+        // byte immediately before the specific name.  Therefore, subtract 1 to check
+        // the Operator.
+        //
+        Operation = DsdtPointer - 1;
+        if (*Operation == AML_OPREGION_OP) {
+          Address  = (UINT32 *)(DsdtPointer + 6);
+          *Address = (UINT32)(UINTN)mGlobalNvsArea.Area;
+          Size     = (UINT16 *)(DsdtPointer + 11);
+          *Size    = sizeof (EFI_GLOBAL_NVS_AREA);
+        }
+
+        break;
+      default:
+        break;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+    Update the MADT table.
+
+    @param  TableHeader   The table to be set.
+
+    @retval  EFI_SUCCESS  Update MADT table sucessfully.
+
+**/
+EFI_STATUS
+PatchMadtTable (
+  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader
+  )
+{
+  EFI_STATUS                                   Status;
+  EFI_MP_SERVICES_PROTOCOL                     *MpService;
+  UINTN                                        NumCPUs = 1;
+  UINTN                                        NumEnabledCPUs;
+  UINT8                                        CurrProcessor = 0;
+  EFI_PROCESSOR_INFORMATION                    ProcessorInfo;
+  UINT8                                        *CurrPtr;
+  EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_STRUCTURE  *ApicPtr   = NULL;
+  EFI_ACPI_5_0_IO_APIC_STRUCTURE               *IoApicPtr = NULL;
+
+  // Find the MP Protocol.
+  Status = gBS->LocateProtocol (
+                  &gEfiMpServiceProtocolGuid,
+                  NULL,
+                  (VOID **)&MpService
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Determine the number of processors
+  MpService->GetNumberOfProcessors (
+               MpService,
+               &NumCPUs,
+               &NumEnabledCPUs
+               );
+
+  CurrPtr  = (UINT8 *)TableHeader;
+  CurrPtr += sizeof (EFI_ACPI_5_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
+  while (CurrPtr < ((UINT8 *)TableHeader + ((EFI_ACPI_COMMON_HEADER *)TableHeader)->Length)) {
+    // Local APIC
+    ApicPtr = (EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_STRUCTURE *)CurrPtr;
+    if (ApicPtr->Type == EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC) {
+      // Disable at first
+      ApicPtr->Flags  = 0;
+      ApicPtr->ApicId = 0;
+
+      // retrieve processor information
+      Status = MpService->GetProcessorInfo (
+                            MpService,
+                            CurrProcessor,
+                            &ProcessorInfo
+                            );
+      if (!EFI_ERROR (Status)) {
+        if (ProcessorInfo.StatusFlag & PROCESSOR_ENABLED_BIT) {
+          ApicPtr->Flags = EFI_ACPI_5_0_LOCAL_APIC_ENABLED;
+        }
+
+        ApicPtr->ApicId = (UINT8)(ProcessorInfo.ProcessorId);
+      }
+
+      // Increment the procesor count
+      CurrProcessor++;
+    }
+
+    // IO APIC (IOHUB and FCH)
+    IoApicPtr = (EFI_ACPI_5_0_IO_APIC_STRUCTURE *)CurrPtr;
+    if (IoApicPtr->Type == EFI_ACPI_5_0_IO_APIC) {
+      // IoApicPtr->IoApicId = PcdGet8 (PcdCfgFchIoapicId);
+      // IoApicPtr->IoApicId = PcdGet8 (PcdCfgGnbIoapicId);
+    }
+
+    // Go to the next structure in the APIC table
+    CurrPtr += (ApicPtr->Length);
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.h b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.h
new file mode 100644
index 0000000000..10e724a2ab
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/AcpiPlatformDxe/AcpiPlatformHooks.h
@@ -0,0 +1,48 @@
+/** @file
+  Sample ACPI Platform Driver
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef ACPI_PLATFORM_HOOKS_H_
+#define ACPI_PLATFORM_HOOKS_H_
+
+//
+// Statements that include other header files
+//
+#include <IndustryStandard/Acpi.h>
+#include <Protocol/MpService.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define AML_OPREGION_OP  0x80
+
+/**
+    Update the DSDT table.
+
+    @param  TableHeader   The table to be set.
+
+    @retval  EFI_SUCCESS  Update DSDT table sucessfully.
+
+**/
+EFI_STATUS
+PatchDsdtTable (
+  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader
+  );
+
+/**
+    Update the MADT table.
+
+    @param  TableHeader   The table to be set.
+
+    @retval  EFI_SUCCESS  Update MADT table successfully.
+
+**/
+EFI_STATUS
+PatchMadtTable (
+  IN OUT   EFI_ACPI_DESCRIPTION_HEADER  *TableHeader
+  );
+
+#endif
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114599): https://edk2.groups.io/g/devel/message/114599
Mute This Topic: https://groups.io/mt/103975478/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 24/32] AMD/VanGoghBoard: Check in FchSpi module
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (22 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 23/32] AMD/VanGoghBoard: Check in AcpiPlatform Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 25/32] AMD/VanGoghBoard: Check in PlatformInitPei module Zhai, MingXin (Duke) via groups.io
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial FchSpi module. FCH SPI Common Driver implements
  the SPI Host Controller Compatibility Interface.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Universal/FchSpi/FchSpiProtect.c          |  67 ++
 .../Universal/FchSpi/FchSpiProtect.h          |  38 +
 .../Universal/FchSpi/FchSpiRuntimeDxe.c       | 163 ++++
 .../Universal/FchSpi/FchSpiRuntimeDxe.h       |  49 ++
 .../Universal/FchSpi/FchSpiRuntimeDxe.inf     |  84 ++
 .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.c | 112 +++
 .../VanGoghBoard/Universal/FchSpi/FchSpiSmm.h |  32 +
 .../Universal/FchSpi/FchSpiSmm.inf            |  94 +++
 .../VanGoghBoard/Universal/FchSpi/SpiCommon.c | 790 ++++++++++++++++++
 .../VanGoghBoard/Universal/FchSpi/SpiInfo.h   |  24 +
 10 files changed, 1453 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h

diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c
new file mode 100644
index 0000000000..658d9b063d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.c
@@ -0,0 +1,67 @@
+/** @file
+  Implements FchSpiProtect.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+
+#include "FchSpiProtect.h"
+
+/**
+
+   Fch Spi Protect Lock
+
+   @param SpiMmioBase
+
+**/
+EFI_STATUS
+EFIAPI
+FchSpiProtect_Lock (
+  IN UINTN  SpiMmioBase
+  )
+{
+  if (!(MmioRead8 (SpiMmioBase + 2) & 0xC0)) {
+    // Check BIT7+BIT6
+    return EFI_SUCCESS;
+  } else {
+    MmioWrite8 (SpiMmioBase + 9, 0x6);                                // PrefixOpCode WRITE_ENABLE
+    MmioWrite8 (SpiMmioBase + 2, MmioRead8 (SpiMmioBase + 2) & 0x3F); // Clear BIT7+BIT6
+    if (MmioRead8 (SpiMmioBase + 2) & 0xC0) {
+      return EFI_DEVICE_ERROR;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+   Fch Spi Protect UnLock
+
+   @param SpiMmioBase
+
+**/
+EFI_STATUS
+EFIAPI
+FchSpiProtect_UnLock (
+  IN UINTN  SpiMmioBase
+  )
+{
+  if ((MmioRead8 (SpiMmioBase + 2) & 0xC0) || (6 != MmioRead8 (SpiMmioBase + 9))) {
+    return EFI_SUCCESS;
+  } else {
+    MmioWrite8 (SpiMmioBase + 9, 0x0);
+    MmioWrite8 (SpiMmioBase + 2, MmioRead8 (SpiMmioBase + 2) | 0xC0); // Set BIT7+BIT6
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h
new file mode 100644
index 0000000000..e46a1a066a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiProtect.h
@@ -0,0 +1,38 @@
+/** @file
+  Implements FchSpiProtect.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FCH_SPI_PROTECT_H_
+#define FCH_SPI_PROTECT_H_
+
+/**
+
+   Fch Spi Protect Lock
+
+   @param UINTN SpiMmioBase
+
+**/
+EFI_STATUS
+EFIAPI
+FchSpiProtect_Lock (
+  IN UINTN  SpiMmioBase
+  );
+
+/**
+
+   Fch Spi Protect UnLock
+
+   @param UINTN SpiMmioBase
+
+**/
+EFI_STATUS
+EFIAPI
+FchSpiProtect_UnLock (
+  IN UINTN  SpiMmioBase
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c
new file mode 100644
index 0000000000..7bb402402c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.c
@@ -0,0 +1,163 @@
+/** @file
+PCH SPI Runtime Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifdef _MSC_VER
+  #pragma optimize( "", off )
+#endif
+
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC push_options
+    #pragma GCC optimize ("O0")
+  #else
+    #pragma clang optimize off
+  #endif
+#endif
+
+#include "FchSpiRuntimeDxe.h"
+
+extern EFI_GUID  gEfiEventVirtualAddressChangeGuid;
+CONST BOOLEAN    gInSmm = FALSE;
+
+//
+// Global variables
+//
+SPI_INSTANCE  *mSpiInstance;
+
+/**
+
+  Fixup internal data pointers so that the services can be called in virtual mode.
+
+  @param Event     The event registered.
+  @param Context   Event context. Not used in this event handler.
+
+  @retval   None
+
+**/
+VOID
+EFIAPI
+FchSpiVirtualddressChangeEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiBar));
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiProtocol.Init));
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiProtocol.Lock));
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance->SpiProtocol.Execute));
+  gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *)&(mSpiInstance));
+}
+
+/**
+
+  Entry point for the SPI host controller driver.
+
+  @param ImageHandle       Image handle of this driver.
+  @param SystemTable       Global system service table.
+
+  @retval EFI_SUCCESS           Initialization complete.
+  @retval EFI_UNSUPPORTED       The chipset is unsupported by this driver.
+  @retval EFI_OUT_OF_RESOURCES  Do not have enough resources to initialize the driver.
+  @retval EFI_DEVICE_ERROR      Device error, driver exits abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallFchSpiRuntimeDxe (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                       Status;
+  UINT64                           BaseAddress;
+  UINT64                           Length;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  GcdMemorySpaceDescriptor;
+  UINT64                           Attributes;
+  EFI_EVENT                        Event;
+
+  DEBUG ((DEBUG_INFO, "InstallFchSpiRuntimeDxe() Start\n"));
+
+  //
+  // Allocate Runtime memory for the SPI protocol instance.
+  //
+  mSpiInstance = AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE));
+  if (mSpiInstance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the SPI protocol instance
+  //
+  Status = SpiProtocolConstructor (mSpiInstance);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Install the EFI_SPI_PROTOCOL interface
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &(mSpiInstance->Handle),
+                  &gEfiSpiProtocolGuid,
+                  &(mSpiInstance->SpiProtocol),
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    FreePool (mSpiInstance);
+    return EFI_DEVICE_ERROR;
+  }
+
+  Status = mSpiInstance->SpiProtocol.Init (&(mSpiInstance->SpiProtocol));
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Set Spi space in GCD to be RUNTIME so that the range will be supported in
+  // virtual address mode in EFI aware OS runtime.
+  // It will assert if Spi Memory Space is not allocated
+  // The caller is responsible for the existence and allocation of the Spi Memory Spaces
+  //
+  BaseAddress = (EFI_PHYSICAL_ADDRESS)(mSpiInstance->SpiBar);
+  Length      = 0x1000;
+
+  Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDescriptor);
+  ASSERT_EFI_ERROR (Status);
+
+  Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;
+
+  Status = gDS->SetMemorySpaceAttributes (
+                  BaseAddress,
+                  Length,
+                  Attributes
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  FchSpiVirtualddressChangeEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &Event
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "InstallFchSpiRuntimeDxe() End\n"));
+
+  return EFI_SUCCESS;
+}
+
+#ifdef _MSC_VER
+  #pragma optimize( "", on )
+#endif
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC pop_options
+  #endif
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h
new file mode 100644
index 0000000000..929e821294
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.h
@@ -0,0 +1,49 @@
+/** @file
+Header file for the PCH SPI Runtime Driver.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FCH_SPI_RUNTIME_DXE_H_
+#define FCH_SPI_RUNTIME_DXE_H_
+
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/TimerLib.h>
+#include <Library/SpiFlashDeviceLib.h>
+
+#include <Protocol/Spi.h>
+#include <Protocol/SpiCommon.h>
+
+#define EFI_INTERNAL_POINTER  0x00000004
+
+/**
+
+  Fixup internal data pointers so that the services can be called in virtual mode.
+
+  @param Event     The event registered.
+  @param Context   Event context. Not used in this event handler.
+
+  @retval   None
+
+**/
+VOID
+EFIAPI
+FchSpiVirtualddressChangeEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf
new file mode 100644
index 0000000000..c2af195d05
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiRuntimeDxe.inf
@@ -0,0 +1,84 @@
+## @file
+#    Component description file for the SPI Runtime driver.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FchSpiRuntimeDxe
+  FILE_GUID                      = B9B0740A-B4E9-46FF-AAC7-C632BAC15834
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InstallFchSpiRuntimeDxe
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+[Sources]
+  FchSpiRuntimeDxe.c
+  FchSpiRuntimeDxe.h
+  FchSpiProtect.c
+  FchSpiProtect.h
+  SpiCommon.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+[Packages]
+  MdePkg/MdePkg.dec
+  ChachaniBoardPkg/Project.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+#                         this module.
+#
+################################################################################
+[LibraryClasses]
+  UefiRuntimeServicesTableLib
+  UefiRuntimeLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  TimerLib
+  DxeServicesTableLib
+  UefiLib
+  DebugLib
+  MemoryAllocationLib
+  PciExpressLib
+  SpiFlashDeviceLib
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+#                           that this module uses or produces.
+#
+################################################################################
+[Protocols]
+  gEfiSpiProtocolGuid
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
+
+[Depex]
+  TRUE
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c
new file mode 100644
index 0000000000..1f842685a8
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.c
@@ -0,0 +1,112 @@
+/** @file
+
+PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+
+**/
+#ifdef _MSC_VER
+  #pragma optimize( "", off )
+#endif
+
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC push_options
+    #pragma GCC optimize ("O0")
+  #else
+    #pragma clang optimize off
+  #endif
+#endif
+
+#include "FchSpiSmm.h"
+
+CONST BOOLEAN  gInSmm = TRUE;
+
+//
+// Global variables
+//
+SPI_INSTANCE  *mSpiInstance;
+
+/**
+
+  Entry point for the SPI host controller driver.
+
+  @param ImageHandle       Image handle of this driver.
+  @param SystemTable       Global system service table.
+
+  @retval EFI_SUCCESS           Initialization complete.
+  @retval EFI_UNSUPPORTED       The chipset is unsupported by this driver.
+  @retval EFI_OUT_OF_RESOURCES  Do not have enough resources to initialize the driver.
+  @retval EFI_DEVICE_ERROR      Device error, driver exits abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallFchSpiSmm (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  // VOID                            *SmmReadyToBootRegistration;
+
+  DEBUG ((DEBUG_INFO, "InstallFchSpiSmm() Start\n"));
+
+  Status = gSmst->SmmAllocatePool (
+                    EfiRuntimeServicesData,
+                    sizeof (SPI_INSTANCE),
+                    (VOID **)&mSpiInstance
+                    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ZeroMem (mSpiInstance, sizeof (SPI_INSTANCE));
+
+  if (mSpiInstance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the SPI protocol instance
+  //
+  Status = SpiProtocolConstructor (mSpiInstance);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Install the EFI_SPI_PROTOCOL interface
+  //
+  Status = gSmst->SmmInstallProtocolInterface (
+                    &(mSpiInstance->Handle),
+                    &gEfiSmmSpiProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &(mSpiInstance->SpiProtocol)
+                    );
+  if (EFI_ERROR (Status)) {
+    FreePool (mSpiInstance);
+    return EFI_DEVICE_ERROR;
+  }
+
+  Status = mSpiInstance->SpiProtocol.Init (&(mSpiInstance->SpiProtocol));
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "InstallFchSpiSmm() End\n"));
+
+  return EFI_SUCCESS;
+}
+
+#ifdef _MSC_VER
+  #pragma optimize( "", on )
+#endif
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC pop_options
+  #endif
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h
new file mode 100644
index 0000000000..e7e9ed6033
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.h
@@ -0,0 +1,32 @@
+/** @file
+Header file for the PCH SPI SMM Driver.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FCH_SPI_SMM_H_
+#define FCH_SPI_SMM_H_
+
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PciExpressLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciLib.h>
+#include <Library/TimerLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/SpiFlashDeviceLib.h>
+
+#include <Protocol/SmmReadyToBoot.h>
+#include <Protocol/Spi.h>
+#include <Protocol/SpiCommon.h>
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf
new file mode 100644
index 0000000000..b30a17119d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/FchSpiSmm.inf
@@ -0,0 +1,94 @@
+## @file
+# Spi smm driver
+#
+# Component description file for the SPI SMM driver.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2013-2015 Intel Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FchSpiSmm
+  FILE_GUID                      = 9D63F99F-609D-4EB3-A9D1-5ACE2E25792A
+  MODULE_TYPE                    = DXE_SMM_DRIVER
+  VERSION_STRING                 = 1.1
+  PI_SPECIFICATION_VERSION       = 0x0001000A
+  ENTRY_POINT                    = InstallFchSpiSmm
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+[Sources]
+  FchSpiSmm.c
+  FchSpiSmm.h
+  FchSpiProtect.c
+  FchSpiProtect.h
+  SpiCommon.c
+
+[sources.ia32]
+
+[sources.x64]
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+#                         this module.
+#
+################################################################################
+[LibraryClasses]
+  BaseLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  TimerLib
+  DxeServicesTableLib
+  UefiLib
+  DebugLib
+  MemoryAllocationLib
+  PciExpressLib
+  SmmServicesTableLib
+  SpiFlashDeviceLib
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+#                           that this module uses or produces.
+#
+################################################################################
+[Protocols]
+  gEfiSmmSpiProtocolGuid
+  gEfiSmmBase2ProtocolGuid
+  gEdkiiSmmReadyToBootProtocolGuid
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
+
+[Depex]
+   gEfiSmmBase2ProtocolGuid
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c
new file mode 100644
index 0000000000..4aab7294cb
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiCommon.c
@@ -0,0 +1,790 @@
+/** @file
+PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2013-2015 Intel Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifdef _MSC_VER
+  #pragma optimize( "", off )
+#endif
+
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC push_options
+    #pragma GCC optimize ("O0")
+  #else
+    #pragma clang optimize off
+  #endif
+#endif
+
+#include "FchSpiProtect.h"
+#include "SpiInfo.h"
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/SpiFlashDeviceLib.h>
+#include <Protocol/SpiCommon.h>
+#include <Protocol/SmmBase2.h>
+
+#define SPI_WREN_INDEX  0                     // Prefix Opcode 0: SPI_COMMAND_WRITE_ENABLE
+#define SPI_EWSR_INDEX  1                     // Prefix Opcode 1: SPI_COMMAND_WRITE_S_EN
+
+#define FCH_SPI_MMIO_REG48_TXBYTECOUNT  0x48
+#define FCH_SPI_MMIO_REG4B_RXBYTECOUNT  0x4B
+#define FCH_SPI_MMIO_REG80_FIFO         0x80
+#define FCH_SPI_MMIO_REG50_ADDR32CTRL0  0x50
+#define FCH_SPI_MMIO_REG5C_ADDR32CTRL3  0x5C
+
+volatile UINTN        mFchSpiProtect_LOCKED_ReadyToBoot = FALSE;
+volatile UINTN        mSpiMmioBase;
+extern CONST BOOLEAN  gInSmm;
+volatile BOOLEAN      mSupport4ByteAddrFlag = FALSE;
+
+STATIC
+EFI_STATUS
+WaitForSpiDeviceWriteEnabled (
+  IN  EFI_SPI_PROTOCOL  *This
+  );
+
+/**
+
+  Initialize an SPI protocol instance.
+  The function will assert in debug if FCH SPI has not been initialized
+
+  @param SpiInstance   - Pointer to SpiInstance to initialize
+
+  @retval EFI_SUCCESS     The protocol instance was properly initialized
+  @retval EFI_UNSUPPORTED The FCH is not supported by this module
+
+**/
+EFI_STATUS
+SpiProtocolConstructor (
+  SPI_INSTANCE  *SpiInstance
+  )
+{
+  DEBUG ((DEBUG_INFO, "SpiProtocolConstructor enter!\n"));
+
+  SpiInstance->InitDone = FALSE;  // Indicate NOT READY.
+  //
+  // Initialize the SPI protocol instance
+  //
+  SpiInstance->Signature           = FCH_SPI_PRIVATE_DATA_SIGNATURE;
+  SpiInstance->Handle              = NULL;
+  SpiInstance->SpiProtocol.Init    = SpiProtocolInit;
+  SpiInstance->SpiProtocol.Lock    = SpiProtocolLock;
+  SpiInstance->SpiProtocol.Execute = SpiProtocolExecute;
+
+  //
+  // Sanity check to ensure FCH SPI initialization has occurred previously.
+  //
+  SpiInstance->SpiBar = (EFI_PHYSICAL_ADDRESS)PciRead32 (
+                                                PCI_LIB_ADDRESS (
+                                                  0,
+                                                  20,
+                                                  3,
+                                                  0xA0
+                                                  )
+                                                )&0x00000000FFFFFFE0;
+  ASSERT (SpiInstance->SpiBar != 0);
+  mSpiMmioBase = SpiInstance->SpiBar;
+
+  DEBUG ((DEBUG_VERBOSE, "SpiInstance->SpiBar = 0x%x\n", SpiInstance->SpiBar));
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Initialize the host controller to execute SPI command.
+
+  @param This                    Pointer to the EFI_SPI_PROTOCOL instance.
+
+  @retval EFI_SUCCESS             Initialization completed.
+  @retval EFI_ACCESS_DENIED       The SPI static configuration interface has been locked-down.
+  @retval EFI_INVALID_PARAMETER   Bad input parameters.
+  @retval EFI_UNSUPPORTED         Can't get Descriptor mode VSCC values
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolInit (
+  IN EFI_SPI_PROTOCOL  *This
+  )
+{
+  EFI_STATUS    Status;
+  SPI_INSTANCE  *SpiInstance;
+  UINT8         FlashPartId[3];
+  UINT8         FlashIndex;
+
+  DEBUG ((DEBUG_INFO, "SpiProtocolInit enter!\n"));
+
+  SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+  CopyMem (&SpiInstance->SpiInitTable, &mSpiInitTable[0], sizeof (SPI_INIT_TABLE));
+
+  Status = SpiProtocolExecute (
+             This,
+             SPI_OPCODE_JEDEC_ID_INDEX,
+             0,
+             TRUE,
+             TRUE,
+             FALSE,
+             (UINTN)0,
+             3,
+             FlashPartId,
+             EnumSpiRegionDescriptor
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (FlashIndex = 0; FlashIndex < mNumSpiFlashMax; FlashIndex++) {
+    CopyMem (&SpiInstance->SpiInitTable, &mSpiInitTable[FlashIndex], sizeof (SPI_INIT_TABLE));
+
+    if ((FlashPartId[0] != SpiInstance->SpiInitTable.VendorId) ||
+        (FlashPartId[1] != SpiInstance->SpiInitTable.DeviceId0) ||
+        (FlashPartId[2] != SpiInstance->SpiInitTable.DeviceId1))
+    {
+      DEBUG ((
+        DEBUG_INFO,
+        "SpiProtocolInit()   Target SPI Flash Device [VendorID 0x%02x, DeviceID 0x%02x%02x]  ",
+        FlashPartId[0],
+        FlashPartId[1],
+        FlashPartId[2]
+        ));
+      DEBUG ((
+        DEBUG_INFO,
+        "but Current SPI Flash device [VendorId 0x%02x, DeviceID 0x%02x%02x]!\n",
+        SpiInstance->SpiInitTable.VendorId,
+        SpiInstance->SpiInitTable.DeviceId0,
+        SpiInstance->SpiInitTable.DeviceId1
+        )
+        );
+    } else {
+      DEBUG ((
+        DEBUG_INFO,
+        "Smm Mode: Supported SPI Flash device found, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
+        FlashPartId[0],
+        FlashPartId[1],
+        FlashPartId[2]
+        ));
+      break;
+    }
+  }
+
+  if (FlashIndex >= mNumSpiFlashMax) {
+    Status = EFI_UNSUPPORTED;
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR - Unknown SPI Flash Device, Vendor Id: 0x%02x, Device ID: 0x%02x%02x!\n",
+      FlashPartId[0],
+      FlashPartId[1],
+      FlashPartId[2]
+      ));
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  SpiInstance->InitDone = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Lock the SPI Static Configuration Interface.
+  Once locked, the interface can not be changed and can only be clear by system reset.
+
+  @param This      Pointer to the EFI_SPI_PROTOCOL instance.
+
+  @retval EFI_SUCCESS             Lock operation succeed.
+  @retval EFI_DEVICE_ERROR        Device error, operation failed.
+  @retval EFI_ACCESS_DENIED       The interface has already been locked.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolLock (
+  IN EFI_SPI_PROTOCOL  *This
+  )
+{
+  if (gInSmm) {
+    // Trigger FCH SPI Protect/Lock
+    if (EFI_SUCCESS == FchSpiProtect_Lock (mSpiMmioBase)) {
+      mFchSpiProtect_LOCKED_ReadyToBoot = TRUE;
+      DEBUG ((DEBUG_INFO, "Set FchSpiProtect to LOCK SUCCESS! \n"));
+    } else {
+      DEBUG ((DEBUG_INFO, "Set FchSpiProtect to LOCK FAILED!!! \n"));
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Execute SPI commands from the host controller.
+  This function would be called by runtime driver, please do not use any MMIO marco here
+
+  @param This              Pointer to the EFI_SPI_PROTOCOL instance.
+  @param OpcodeIndex       Index of the command in the OpCode Menu.
+  @param PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+  @param DataCycle         TRUE if the SPI cycle contains data
+  @param Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  @param ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  @param Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                    Region, this value specifies the offset from the Region Base; for BIOS Region,
+                    this value specifies the offset from the start of the BIOS Image. In Non
+                    Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                    Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                    Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                    supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                    the flash (in Non Descriptor Mode)
+  @param DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
+                    data transfer into multiple operations. This function ensures each operation does
+                    not cross 256 byte flash address boundary.
+                    *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+                    (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+                    function to cut the data transfer at proper address boundaries, and it's the
+                    caller's reponsibility to pass in a properly cut DataByteCount parameter.
+  @param Buffer            Pointer to caller-allocated buffer containing the dada received or sent during the
+                    SPI cycle.
+  @param SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                    EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                    Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                    and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                    to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+  @retval EFI_SUCCESS             Command succeed.
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+  @retval EFI_UNSUPPORTED         Command not supported.
+  @retval EFI_DEVICE_ERROR        Device error, command aborts abnormally.
+
+**/
+EFI_STATUS
+EFIAPI
+SpiProtocolExecute (
+  IN     EFI_SPI_PROTOCOL  *This,
+  IN     UINT8             OpcodeIndex,
+  IN     UINT8             PrefixOpcodeIndex,
+  IN     BOOLEAN           DataCycle,
+  IN     BOOLEAN           Atomic,
+  IN     BOOLEAN           ShiftOut,
+  IN     UINTN             Address,
+  IN     UINT32            DataByteCount,
+  IN OUT UINT8             *Buffer,
+  IN     SPI_REGION_TYPE   SpiRegionType
+  )
+{
+  EFI_STATUS  Status;
+  UINT8       SpiStatus;
+
+  //
+  // Check if the parameters are valid.
+  //
+  if ((OpcodeIndex >= SPI_NUM_OPCODE) || (PrefixOpcodeIndex >= SPI_NUM_PREFIX_OPCODE)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (gInSmm) {
+    if (mFchSpiProtect_LOCKED_ReadyToBoot) {
+      FchSpiProtect_UnLock (mSpiMmioBase);
+      DEBUG ((DEBUG_INFO, "FchSpiProtect UnLock!\n"));
+    }
+  }
+
+  SendSpiCmd (
+    This,
+    SPI_OPCODE_READ_S_INDEX,
+    0,
+    TRUE,
+    FALSE,
+    FALSE,
+    0,
+    1,
+    &SpiStatus,
+    EnumSpiRegionAll
+    );
+  if ((SpiStatus & 1) != 0) {
+    if ((OpcodeIndex == SPI_OPCODE_ERASE_INDEX) && (ShiftOut == FALSE)) {
+      return EFI_ALREADY_STARTED;
+    }
+
+    DEBUG ((DEBUG_INFO, "SPI Busy, WaitForSpiCycleComplete\n"));
+    WaitForSpiCycleComplete (This);
+  }
+
+  //
+  // Enter 4 bytes address
+  //
+  if (MmioRead8 (mSpiMmioBase+FCH_SPI_MMIO_REG50_ADDR32CTRL0) & BIT0) {
+    DEBUG ((DEBUG_INFO, "Enter 4-Byte address mode\n"));
+    mSupport4ByteAddrFlag = TRUE;
+    Status                = SendSpiCmd (
+                              This,
+                              SPI_COMMAND_Enter_4Byte_Addr_INDEX,
+                              SPI_WREN_INDEX,
+                              FALSE,
+                              TRUE,
+                              FALSE,
+                              0,
+                              0,
+                              NULL,
+                              EnumSpiRegionDescriptor
+                              );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Enter 4-Byte address mode fail\n"));
+      goto Exit;
+    }
+  }
+
+  //
+  // Sends the command to the SPI interface to execute.
+  //
+  Status = SendSpiCmd (
+             This,
+             OpcodeIndex,
+             PrefixOpcodeIndex,
+             DataCycle,
+             Atomic,
+             ShiftOut,
+             Address,
+             DataByteCount,
+             Buffer,
+             SpiRegionType
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Operate SPI Flash fail\n"));
+    goto Exit;
+  }
+
+  //
+  // Exit 32-bit address
+  //
+  if (mSupport4ByteAddrFlag) {
+    mSupport4ByteAddrFlag = FALSE;
+    Status                = SendSpiCmd (
+                              This,
+                              SPI_COMMAND_Exit_4Byte_Addr_INDEX,
+                              SPI_WREN_INDEX,
+                              FALSE,
+                              TRUE,
+                              FALSE,
+                              0,
+                              0,
+                              NULL,
+                              EnumSpiRegionDescriptor
+                              );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Exit 4-Byte address mode fail\n"));
+      goto Exit;
+    }
+  }
+
+Exit:
+  if (gInSmm) {
+    if (mFchSpiProtect_LOCKED_ReadyToBoot) {
+      FchSpiProtect_Lock (mSpiMmioBase);
+      DEBUG ((DEBUG_INFO, "FchSpiProtect Lock again!\n"));
+    }
+  }
+
+  return Status;
+}
+
+/**
+
+  Waits for SPI device not busy
+
+  @param SpiBar           The SPI Bar Address
+
+  @retval EFI_SUCCESS     Function successfully returned
+  @retval EFI_TIMEOUT     timeout, SPI device busy more than 6s.
+
+**/
+EFI_STATUS
+FchSpiControllerNotBusy (
+  UINTN  SpiBar
+  )
+{
+  volatile  UINT32  SpiStatus;
+  UINT64            WaitTicks;
+  UINT64            WaitCount;
+
+  //
+  // Convert the wait period allowed into to tick count
+  //
+  WaitCount = WAIT_TIME / WAIT_PERIOD;
+  //
+  // Wait until SPI Conroller Not Busy
+  //
+  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+    SpiStatus = MmioRead32 (SpiBar + FCH_SPI_MMIO_REG4C);
+    if (SpiStatus & FCH_SPI_BUSY) {
+      MicroSecondDelay (WAIT_PERIOD);
+    } else {
+      return EFI_SUCCESS;
+    }
+  }
+
+  return EFI_TIMEOUT;
+}
+
+STATIC
+EFI_STATUS
+ResetFifoIndex (
+  SPI_INSTANCE  *SpiInstance
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+
+  This function sends the programmed SPI command to the slave device.
+
+  @param OpcodeIndex       Index of the command in the OpCode Menu.
+  @param PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence.
+  @param DataCycle         TRUE if the SPI cycle contains data
+  @param Atomic            TRUE if the SPI cycle is atomic and interleave cycles are not allowed.
+  @param ShiftOut          If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in.
+  @param Address           In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform
+                           Region, this value specifies the offset from the Region Base; for BIOS Region,
+                           this value specifies the offset from the start of the BIOS Image. In Non
+                           Descriptor Mode, this value specifies the offset from the start of the BIOS Image.
+                           Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor
+                           Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is
+                           supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or
+                           the flash (in Non Descriptor Mode)
+  @param DataByteCount     Number of bytes in the data portion of the SPI cycle. This function may break the
+                           data transfer into multiple operations. This function ensures each operation does
+                           not cross 256 byte flash address boundary.
+                           *NOTE: if there is some SPI chip that has a stricter address boundary requirement
+                           (e.g., its write page size is < 256 byte), then the caller cannot rely on this
+                           function to cut the data transfer at proper address boundaries, and it's the
+                           caller's reponsibility to pass in a properly cut DataByteCount parameter.
+  @param Buffer            Data received or sent during the SPI cycle.
+  @param SpiRegionType     SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe,
+                           EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in
+                           Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode
+                           and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative
+                           to base of the 1st flash device (i.e., it is a Flash Linear Address).
+
+  @retval EFI_SUCCESS             SPI command completes successfully.
+  @retval EFI_DEVICE_ERROR        Device error, the command aborts abnormally.
+  @retval EFI_ACCESS_DENIED       Some unrecognized command encountered in hardware sequencing mode
+  @retval EFI_INVALID_PARAMETER   The parameters specified are not valid.
+
+**/
+EFI_STATUS
+SendSpiCmd (
+  IN     EFI_SPI_PROTOCOL  *This,
+  IN     UINT8             OpcodeIndex,
+  IN     UINT8             PrefixOpcodeIndex,
+  IN     BOOLEAN           DataCycle,
+  IN     BOOLEAN           Atomic,
+  IN     BOOLEAN           ShiftOut,
+  IN     UINTN             Address,
+  IN     UINT32            DataByteCount,
+  IN OUT UINT8             *Buffer,
+  IN     SPI_REGION_TYPE   SpiRegionType
+  )
+{
+  SPI_INSTANCE           *SpiInstance;
+  UINTN                  SpiBiosSize;
+  UINT32                 SpiDataCount;
+  UINT32                 TxByteCount;
+  UINT32                 RxByteCount;
+  UINTN                  Addr, Retry;
+  INTN                   Index, CountIndex;
+  UINTN                  SpiBar;
+  BOOLEAN                WriteFlag;
+  BOOLEAN                AddressFlag;
+  UINT8                  PrefixOpcode;
+  SPI_OPCODE_MENU_ENTRY  OPCodeMenu;
+  UINT8                  Dummy;
+  UINT8                  AddressByteNum;
+
+  SpiInstance    = SPI_INSTANCE_FROM_SPIPROTOCOL (This);
+  SpiBiosSize    = SpiInstance->SpiInitTable.BiosSize;
+  OPCodeMenu     = SpiInstance->SpiInitTable.OpcodeMenu[OpcodeIndex];
+  PrefixOpcode   = SpiInstance->SpiInitTable.PrefixOpcode[PrefixOpcodeIndex];
+  SpiBar         = SpiInstance->SpiBar;
+  Dummy          = 0;
+  AddressByteNum = 3;
+
+  AddressFlag  = (OPCodeMenu.Type == EnumSpiOpcodeWrite);
+  WriteFlag    = AddressFlag;
+  AddressFlag |= (OPCodeMenu.Type == EnumSpiOpcodeRead);
+  WriteFlag   |= (OPCodeMenu.Type == EnumSpiOpcodeWriteNoAddr);
+
+  //
+  // Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0
+  //
+  if (SpiBiosSize == 0) {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ((DataCycle == FALSE) && (DataByteCount > 0)) {
+    DataByteCount = 0;
+  }
+
+  do {
+    SpiDataCount = DataByteCount;
+    TxByteCount  = 0;
+    RxByteCount  = 0;
+
+    //
+    // Calculate the number of bytes to shift in/out during the SPI data cycle.
+    // Valid settings for the number of bytes duing each data portion of the
+    // FCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64
+    //
+    if ((Address & 0xFF) == 0) {
+      SpiDataCount = (DataByteCount > 0x100) ? 0x100 : DataByteCount;
+    } else {
+      SpiDataCount = (DataByteCount > ((~Address + 1) & 0xFF)) ? ((~Address + 1) & 0xFF) : DataByteCount;
+    }
+
+    SpiDataCount = (SpiDataCount > 64) ? 64 : SpiDataCount;
+
+    if (Atomic) {
+      Retry = 0;
+      do {
+        MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG45, PrefixOpcode);
+        MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG48_TXBYTECOUNT, 0);
+        MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG4B_RXBYTECOUNT, 0);
+        MmioOr8 (SpiBar + FCH_SPI_MMIO_REG47, FCH_SPI_EXEC_OPCODE);
+        if (EFI_ERROR (FchSpiControllerNotBusy (SpiBar))) {
+          return EFI_DEVICE_ERROR;
+        }
+
+        if (PrefixOpcodeIndex == SPI_WREN_INDEX) {
+          if (WaitForSpiDeviceWriteEnabled (This) == EFI_SUCCESS) {
+            Retry = 0;
+          } else {
+            Retry++;
+            if (Retry >= 3) {
+              return EFI_DEVICE_ERROR;
+            }
+          }
+        }
+      } while (Retry);
+    }
+
+    Index = 0;
+    //
+    // Check Address Mode
+    //
+    if (AddressFlag) {
+      ResetFifoIndex (SpiInstance);
+      Addr = (UINTN)Address;
+      // if not SPI_COMMAND_READ_SFDP and 32bit address
+      if ((OPCodeMenu.Code != SPI_COMMAND_READ_SFDP) && mSupport4ByteAddrFlag) {
+        AddressByteNum = 4;
+        Addr           = Addr | (UINT32)((MmioRead8 (SpiBar+FCH_SPI_MMIO_REG5C_ADDR32CTRL3) & BIT0) << 24);
+      }
+
+      for (CountIndex = 0; CountIndex < AddressByteNum; CountIndex++) {
+        MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index, (UINT8)((Addr >> (AddressByteNum - CountIndex - 1) * 8) & 0xff));
+        Index++;
+      }
+
+      TxByteCount += AddressByteNum;
+    }
+
+    if ((OPCodeMenu.Code == SPI_COMMAND_READ_SFDP) || (OPCodeMenu.Code == SPI_COMMAND_RPMC_OP2)) {
+      MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index, Dummy);
+      Index++;
+      TxByteCount += 1;
+    }
+
+    if (DataCycle) {
+      //
+      // Check Read/Write Mode
+      //
+      if (WriteFlag) {
+        TxByteCount += SpiDataCount;
+        for (CountIndex = 0; CountIndex < (INTN)(SpiDataCount); CountIndex++) {
+          MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index, Buffer[CountIndex]);
+          Index++;
+        }
+      } else {
+        RxByteCount = SpiDataCount;
+      }
+    }
+
+    // Set SPI Command
+    MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG45, OPCodeMenu.Code);
+    MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG48_TXBYTECOUNT, (UINT8)TxByteCount);
+    MmioWrite8 (SpiBar + FCH_SPI_MMIO_REG4B_RXBYTECOUNT, (UINT8)RxByteCount);
+    MmioOr8 (SpiBar + FCH_SPI_MMIO_REG47, FCH_SPI_EXEC_OPCODE);
+    if (EFI_ERROR (FchSpiControllerNotBusy (SpiBar))) {
+      return EFI_DEVICE_ERROR;
+    }
+
+    if (ShiftOut) {
+      Retry = 0;
+      do {
+        if (WaitForSpiCycleComplete (This)) {
+          Retry = 0;
+        } else {
+          Retry++;
+          if (Retry >= FCH_SPI_RETRY_TIMES) {
+            return EFI_DEVICE_ERROR;
+          }
+        }
+      } while (Retry);
+    }
+
+    if (DataCycle && RxByteCount) {
+      //
+      // Reset Fifo Ptr
+      //
+      ResetFifoIndex (SpiInstance);
+
+      for (CountIndex = 0; CountIndex < (INTN)(SpiDataCount); CountIndex++) {
+        Buffer[CountIndex] = MmioRead8 (SpiBar + FCH_SPI_MMIO_REG80_FIFO + Index);
+        Index++;
+      }
+    }
+
+    //
+    // If shifts data in, get data from the SPI data buffer.
+    //
+    Address       += SpiDataCount;
+    Buffer        += SpiDataCount;
+    DataByteCount -= SpiDataCount;
+  } while (DataByteCount > 0);
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Wait execution cycle to complete on the SPI interface. Check both Hardware
+  and Software Sequencing status registers
+
+  @param This   The SPI protocol instance
+
+  @retval TRUE  SPI cycle completed on the interface.
+  @retval FALSE Time out while waiting the SPI cycle to complete.
+             It's not safe to program the next command on the SPI interface.
+
+**/
+BOOLEAN
+WaitForSpiCycleComplete (
+  IN     EFI_SPI_PROTOCOL  *This
+  )
+{
+  UINT8   SpiStatus;
+  UINT64  WaitTicks;
+  UINT64  WaitCount;
+
+  //
+  // Convert the wait period allowed into to tick count
+  //
+  WaitCount = WAIT_TIME / WAIT_PERIOD;
+
+  //
+  // Wait for the SPI cycle to complete.
+  //
+  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+    //
+    // Execute Read Status Command
+    //
+    SendSpiCmd (
+      This,
+      SPI_OPCODE_READ_S_INDEX,
+      0,
+      TRUE,
+      FALSE,
+      FALSE,
+      0,
+      1,
+      &SpiStatus,
+      EnumSpiRegionAll
+      );
+
+    if ((SpiStatus & 1) != 0) {
+      MicroSecondDelay (WAIT_PERIOD);
+    } else {
+      return TRUE;
+    }
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "WaitForSpiCycleComplete() Timeout\n"));
+  return FALSE;
+}
+
+/**
+
+  Wait execution cycle to complete on the SPI interface. Check both Hardware
+  and Software Sequencing status registers
+
+  @param This   The SPI protocol instance
+
+  @retval EFI_SUCCESS  SPI cycle completed on the interface.
+  @retval EFI_TIMEOUT  Time out while waiting the SPI cycle to complete.
+             It's not safe to program the next command on the SPI interface.
+
+**/
+STATIC
+EFI_STATUS
+WaitForSpiDeviceWriteEnabled (
+  IN  EFI_SPI_PROTOCOL  *This
+  )
+{
+  UINT8   SpiStatus;
+  UINT64  WaitTicks;
+  UINT64  WaitCount;
+
+  DEBUG ((DEBUG_VERBOSE, "WaitForSpiDeviceWriteEnabled() Enter!\n"));
+
+  //
+  // Convert the wait period allowed into to tick count
+  //
+  WaitCount = WAIT_TIME / WAIT_PERIOD;
+
+  //
+  // Wait for the SPI cycle to complete.
+  //
+  for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) {
+    //
+    // Execute Read Status Command
+    //
+    SendSpiCmd (
+      This,
+      SPI_OPCODE_READ_S_INDEX,
+      0,
+      TRUE,
+      FALSE,
+      FALSE,
+      0,
+      1,
+      &SpiStatus,
+      EnumSpiRegionAll
+      );
+
+    if ((SpiStatus & 2) == 0) {
+      MicroSecondDelay (WAIT_PERIOD);
+    } else {
+      DEBUG ((DEBUG_VERBOSE, "WaitForSpiCycleComplete() Exit\n"));
+      return EFI_SUCCESS;
+    }
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "WaitForSpiDeviceWriteEnabled() Exit Timeout !\n"));
+  return EFI_TIMEOUT;
+}
+
+#ifdef _MSC_VER
+  #pragma optimize( "", on )
+#endif
+#ifdef __GNUC__
+  #ifndef __clang__
+    #pragma GCC pop_options
+  #endif
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h
new file mode 100644
index 0000000000..28b67ea991
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/FchSpi/SpiInfo.h
@@ -0,0 +1,24 @@
+/** @file
+  Implements SpiInfo.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_INFO_H_
+#define SPI_INFO_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Protocol/Spi.h>
+
+#ifdef FCH_SPI_EXEC_OPCODE
+  #undef FCH_SPI_EXEC_OPCODE
+#define FCH_SPI_EXEC_OPCODE  BIT7
+#endif
+
+#define FCH_SPI_MMIO_REG45  0x45             // OpCode Access
+#define FCH_SPI_MMIO_REG47  0x47             // Execute Access
+#define FCH_SPI_MMIO_REG4C  0x4C             // SPI Status
+
+#endif
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114600): https://edk2.groups.io/g/devel/message/114600
Mute This Topic: https://groups.io/mt/103975480/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 25/32] AMD/VanGoghBoard: Check in PlatformInitPei module
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (23 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 24/32] AMD/VanGoghBoard: Check in FchSpi module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 26/32] AMD/VanGoghBoard: Check in Smbios platform dxe drivers Zhai, MingXin (Duke) via groups.io
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Duke Zhai, Igniculus Fu, Abner Chang

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="yes", Size: 366 bytes --]



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114601): https://edk2.groups.io/g/devel/message/114601
Mute This Topic: https://groups.io/mt/103975481/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 26/32] AMD/VanGoghBoard: Check in Smbios platform dxe drivers
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (24 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 25/32] AMD/VanGoghBoard: Check in PlatformInitPei module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg Zhai, MingXin (Duke) via groups.io
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Ken Yao, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial Smbios platform DXE drivers. Static SMBIOS Table for Chachani platform.
  SmbiosLib provides detailed information of Chachani platform.

Signed-off-by: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Duke Zhai <duke.zhai@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../PlatformSmbiosDxe/PlatformSmbiosDxe.c     |  75 ++++
 .../PlatformSmbiosDxe/PlatformSmbiosDxe.inf   |  52 +++
 .../Universal/PlatformSmbiosDxe/SmbiosTable.c | 382 ++++++++++++++++++
 3 files changed, 509 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/SmbiosTable.c

diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.c b/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.c
new file mode 100644
index 0000000000..c4de6ca133
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.c
@@ -0,0 +1,75 @@
+/** @file
+  Static SMBIOS Table for platform
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2012, Apple Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <IndustryStandard/SmBios.h>
+#include <Protocol/Smbios.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SmbiosLib.h>
+#include <Library/HobLib.h>
+
+extern SMBIOS_TEMPLATE_ENTRY  gSmbiosTemplate[];
+
+/**
+  Main entry for this driver.
+
+  @param ImageHandle     Image handle this driver.
+  @param SystemTable     Pointer to SystemTable.
+
+  @retval EFI_SUCESS     This function always complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSmbiosDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                Status;
+  EFI_SMBIOS_HANDLE         SmbiosHandle;
+  SMBIOS_STRUCTURE_POINTER  Smbios;
+
+  DEBUG ((DEBUG_INFO, " PlatfomrSmbiosDriverEntryPoint \n"));
+
+  // Phase 0 - Patch table to make SMBIOS 2.7 structures smaller to conform
+  //           to an early version of the specification.
+
+  // Phase 1 - Initialize SMBIOS tables from template
+  Status = SmbiosLibInitializeFromTemplate (gSmbiosTemplate);
+  ASSERT_EFI_ERROR (Status);
+
+  // Phase 2 - Patch SMBIOS table entries
+  Smbios.Hdr = SmbiosLibGetRecord (EFI_SMBIOS_TYPE_BIOS_INFORMATION, 0, &SmbiosHandle);
+  if (Smbios.Type0 != NULL) {
+    // 64K * (n+1) bytes
+    Smbios.Type0->BiosSize = (UINT8)DivU64x32 (FixedPcdGet64 (PcdFlashAreaSize), 64*1024) - 1;
+
+    SmbiosLibUpdateUnicodeString (
+      SmbiosHandle,
+      Smbios.Type0->BiosVersion,
+      (CHAR16 *)PcdGetPtr (PcdFirmwareVersionString)
+      );
+
+    DEBUG ((
+      DEBUG_INFO,
+      " Smbios.Type0->BiosSize: %dMB, Smbios.Type0->BiosVersion: %S, Build Time: %a,%a\n",
+      (Smbios.Type0->BiosSize +1) * 64 / 1024,
+      (CHAR16 *)PcdGetPtr (PcdFirmwareVersionString),
+      __DATE__,
+      __TIME__
+      ));
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.inf b/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
new file mode 100644
index 0000000000..1f4fefeaa2
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
@@ -0,0 +1,52 @@
+## @file
+# Platform SMBIOS driver that fills in SMBIOS table entries.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2012, Apple Inc. All rights reserved.
+# Portions copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformSmbiosDxe
+  FILE_GUID                      = 15EEEB97-709E-91FA-CDA7-44A9C85DDB78
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PlatformSmbiosDriverEntryPoint
+
+
+[Sources]
+  SmbiosTable.c
+  PlatformSmbiosDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiLib
+  HobLib
+  SmbiosLib
+
+[Protocols]
+  gEfiSmbiosProtocolGuid
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareReleaseDateString
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
+  gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize
+
+[Depex]
+  gEfiSmbiosProtocolGuid
diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/SmbiosTable.c b/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/SmbiosTable.c
new file mode 100644
index 0000000000..2770cd23f3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/SmbiosTable.c
@@ -0,0 +1,382 @@
+/** @file
+  Implements VanGogh board Smbios tables
+  Static SMBIOS Table for platform
+
+  Note SMBIOS 2.7.1 Required structures:
+    BIOS Information (Type 0)
+    System Information (Type 1)
+    System Enclosure (Type 3)
+    Processor Information (Type 4) - CPU Driver
+    Cache Information (Type 7) - For cache that is external to processor
+    System Slots (Type 9) - If system has slots
+    Physical Memory Array (Type 16)
+    Memory Device (Type 17) - For each socketed system-memory Device
+    Memory Array Mapped Address (Type 19) - One per contiguous block per Physical Memroy Array
+    System Boot Information (Type 32)
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2012, Apple Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiDxe.h>
+#include <IndustryStandard/SmBios.h>
+#include <Protocol/Smbios.h>
+#include <Library/SmbiosLib.h>
+
+SMBIOS_TABLE_TYPE0  gSmbiosType0Template = {
+  { EFI_SMBIOS_TYPE_BIOS_INFORMATION, sizeof (SMBIOS_TABLE_TYPE0), 0 },
+  1,                    // Vendor String
+  2,                    // BiosVersion String
+  0xE000,               // BiosSegment
+  3,                    // BiosReleaseDate String
+  0x7F,                 // BiosSize
+  {       // BiosCharacteristics
+    0,    //  Reserved                          :2;  ///< Bits 0-1.
+    0,    //  Unknown                           :1;
+    0,    //  BiosCharacteristicsNotSupported   :1;
+    0,    //  IsaIsSupported                    :1;
+    0,    //  McaIsSupported                    :1;
+    0,    //  EisaIsSupported                   :1;
+    1,    //  PciIsSupported                    :1;
+    0,    //  PcmciaIsSupported                 :1;
+    0,    //  PlugAndPlayIsSupported            :1;
+    0,    //  ApmIsSupported                    :1;
+    1,    //  BiosIsUpgradable                  :1;
+    1,    //  BiosShadowingAllowed              :1;
+    0,    //  VlVesaIsSupported                 :1;
+    0,    //  EscdSupportIsAvailable            :1;
+    0,    //  BootFromCdIsSupported             :1;
+    1,    //  SelectableBootIsSupported         :1;
+    0,    //  RomBiosIsSocketed                 :1;
+    0,    //  BootFromPcmciaIsSupported         :1;
+    0,    //  EDDSpecificationIsSupported       :1;
+    0,    //  JapaneseNecFloppyIsSupported      :1;
+    0,    //  JapaneseToshibaFloppyIsSupported  :1;
+    0,    //  Floppy525_360IsSupported          :1;
+    0,    //  Floppy525_12IsSupported           :1;
+    0,    //  Floppy35_720IsSupported           :1;
+    0,    //  Floppy35_288IsSupported           :1;
+    0,    //  PrintScreenIsSupported            :1;
+    0,    //  Keyboard8042IsSupported           :1;
+    0,    //  SerialIsSupported                 :1;
+    0,    //  PrinterIsSupported                :1;
+    0,    //  CgaMonoIsSupported                :1;
+    0,    //  NecPc98                           :1;
+    0     //  ReservedForVendor                 :32; ///< Bits 32-63. Bits 32-47 reserved for BIOS vendor
+    ///< and bits 48-63 reserved for System Vendor.
+  },
+  {       // BIOSCharacteristicsExtensionBytes[]
+    0x81, //  AcpiIsSupported                   :1;
+          //  UsbLegacyIsSupported              :1;
+          //  AgpIsSupported                    :1;
+          //  I2OBootIsSupported                :1;
+          //  Ls120BootIsSupported              :1;
+          //  AtapiZipDriveBootIsSupported      :1;
+          //  Boot1394IsSupported               :1;
+          //  SmartBatteryIsSupported           :1;
+    //  BIOSCharacteristicsExtensionBytes[1]
+    0x0a, //  BiosBootSpecIsSupported              :1;
+          //  FunctionKeyNetworkBootIsSupported    :1;
+          //  TargetContentDistributionEnabled     :1;
+          //  UefiSpecificationSupported           :1;
+          //  VirtualMachineSupported              :1;
+          //  ExtensionByte2Reserved               :3;
+  },
+  0x00,                    // SystemBiosMajorRelease
+  0x01,                    // SystemBiosMinorRelease
+  0xFF,                    // EmbeddedControllerFirmwareMajorRelease
+  0xFF,                    // EmbeddedControllerFirmwareMinorRelease
+};
+CHAR8               *gSmbiosType0Strings[] = {
+  "ADVANCED MICRO DEVICES, INC.",   // Vendor String
+  __TIME__,                         // BiosVersion String
+  __DATE__,                         // BiosReleaseDate String
+  NULL
+};
+
+SMBIOS_TABLE_TYPE1  gSmbiosType1Template = {
+  { EFI_SMBIOS_TYPE_SYSTEM_INFORMATION, sizeof (SMBIOS_TABLE_TYPE1), 0    },
+  1,    // Manufacturer String
+  2,    // ProductName String
+  3,    // Version String
+  4,    // SerialNumber String
+  { 0x25EF0280,                         0xEC82,                      0x42B0, { 0x8F, 0xB6, 0x10, 0xAD, 0xCC, 0xC6, 0x7C, 0x02}
+  },
+  SystemWakeupTypePowerSwitch,
+  5,    // SKUNumber String
+  6,    // Family String
+};
+CHAR8               *gSmbiosType1Strings[] = {
+  "ADVANCED MICRO DEVICES, INC.",
+  "Chachani",
+  "1.0",
+  "System Serial#",
+  "System SKU#",
+  "edk2",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE2  gSmbiosType2Template = {
+  { EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION, sizeof (SMBIOS_TABLE_TYPE2), 0 },
+  1,    // Manufacturer String
+  2,    // ProductName String
+  3,    // Version String
+  4,    // SerialNumber String
+  5,    // AssetTag String
+  {     // FeatureFlag
+    1,  //  Motherboard           :1;
+    0,  //  RequiresDaughterCard  :1;
+    0,  //  Removable             :1;
+    0,  //  Replaceable           :1;
+    0,  //  HotSwappable          :1;
+    0,  //  Reserved              :3;
+  },
+  6,                        // LocationInChassis String
+  0,                        // ChassisHandle;
+  BaseBoardTypeMotherBoard, // BoardType;
+  0,                        // NumberOfContainedObjectHandles;
+  { 0 }                     // ContainedObjectHandles[1];
+};
+CHAR8               *gSmbiosType2Strings[] = {
+  "ADVANCED MICRO DEVICES, INC.",
+  "Chachani",
+  "1.0",
+  "Base Board Serial#",
+  "Base Board Asset Tag#",
+  "Part Component",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE3  gSmbiosType3Template = {
+  { EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, sizeof (SMBIOS_TABLE_TYPE3), 0 },
+  1,                                                                    // Manufacturer String
+  MiscChassisTypeLapTop,                                                // Type;
+  2,                                                                    // Version String
+  3,                                                                    // SerialNumber String
+  4,                                                                    // AssetTag String
+  ChassisStateSafe,                                                     // BootupState;
+  ChassisStateSafe,                                                     // PowerSupplyState;
+  ChassisStateSafe,                                                     // ThermalState;
+  ChassisSecurityStatusNone,                                            // SecurityStatus;
+  { 0,                                0,                           0, 0}, // OemDefined[4];
+  0,                                                                    // Height;
+  0,                                                                    // NumberofPowerCords;
+  0,                                                                    // ContainedElementCount;
+  0,                                                                    // ContainedElementRecordLength;
+  {
+    { 0 }
+  },                                                                    // ContainedElements[1];
+};
+CHAR8               *gSmbiosType3Strings[] = {
+  "ADVANCED MICRO DEVICES, INC.",
+  "Chachani",
+  "Chassis Board Serial#",
+  "Chassis Board Asset Tag#",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE8  gSmbiosType8Template1 = {
+  { EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE8), 0 },
+  0,                            // InternalReferenceDesignator String
+  PortConnectorTypeNone,        // InternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  1,                            // ExternalReferenceDesignator String
+  PortConnectorTypeNone,        // ExternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  PortTypeOther,                // PortType;                       ///< The enumeration value from MISC_PORT_TYPE.
+};
+CHAR8               *gSmbiosType8Strings1[] = {
+  "Mini DisplayPort",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE8  gSmbiosType8Template2 = {
+  { EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE8), 0 },
+  0,                            // InternalReferenceDesignator String
+  PortConnectorTypeNone,        // InternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  1,                            // ExternalReferenceDesignator String
+  PortConnectorTypeNone,        // ExternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  PortTypeFireWire,             // PortType;                       ///< The enumeration value from MISC_PORT_TYPE.
+};
+CHAR8               *gSmbiosType8Strings2[] = {
+  "FireWire 800",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE8  gSmbiosType8Template3 = {
+  { EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE8), 0 },
+  0,                            // InternalReferenceDesignator String
+  PortConnectorTypeNone,        // InternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  1,                            // ExternalReferenceDesignator String
+  PortConnectorTypeRJ45,        // ExternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  PortTypeNetworkPort,          // PortType;                       ///< The enumeration value from MISC_PORT_TYPE.
+};
+CHAR8               *gSmbiosType8Strings3[] = {
+  "Ethernet",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE8  gSmbiosType8Template4 = {
+  { EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE8), 0 },
+  0,                            // InternalReferenceDesignator String
+  PortConnectorTypeNone,        // InternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  1,                            // ExternalReferenceDesignator String
+  PortConnectorTypeUsb,         // ExternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  PortTypeUsb,                  // PortType;                       ///< The enumeration value from MISC_PORT_TYPE.
+};
+CHAR8               *gSmbiosType8Strings4[] = {
+  "USB0",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE8  gSmbiosType8Template5 = {
+  { EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE8), 0 },
+  0,                            // InternalReferenceDesignator String
+  PortConnectorTypeNone,        // InternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  1,                            // ExternalReferenceDesignator String
+  PortConnectorTypeUsb,         // ExternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  PortTypeUsb,                  // PortType;                       ///< The enumeration value from MISC_PORT_TYPE.
+};
+CHAR8               *gSmbiosType8Strings5[] = {
+  "USB1",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE8  gSmbiosType8Template6 = {
+  { EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE8), 0 },
+  0,                            // InternalReferenceDesignator String
+  PortConnectorTypeNone,        // InternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  1,                            // ExternalReferenceDesignator String
+  PortConnectorTypeUsb,         // ExternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  PortTypeUsb,                  // PortType;                       ///< The enumeration value from MISC_PORT_TYPE.
+};
+CHAR8               *gSmbiosType8Strings6[] = {
+  "USB2",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE8  gSmbiosType8Template7 = {
+  { EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE8), 0 },
+  0,                            // InternalReferenceDesignator String
+  PortConnectorTypeNone,        // InternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  1,                            // ExternalReferenceDesignator String
+  PortConnectorTypeUsb,         // ExternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  PortTypeUsb,                  // PortType;                       ///< The enumeration value from MISC_PORT_TYPE.
+};
+CHAR8               *gSmbiosType8Strings7[] = {
+  "USB3",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE8  gSmbiosType8Template8 = {
+  { EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE8), 0 },
+  0,                                  // InternalReferenceDesignator String
+  PortConnectorTypeNone,              // InternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  1,                                  // ExternalReferenceDesignator String
+  PortConnectorTypeHeadPhoneMiniJack, // ExternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  PortTypeAudioPort,                  // PortType;                       ///< The enumeration value from MISC_PORT_TYPE.
+};
+CHAR8               *gSmbiosType8Strings8[] = {
+  "Audio Line In",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE8  gSmbiosType8Template9 = {
+  { EFI_SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE8), 0 },
+  0,                                  // InternalReferenceDesignator String
+  PortConnectorTypeNone,              // InternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  1,                                  // ExternalReferenceDesignator String
+  PortConnectorTypeHeadPhoneMiniJack, // ExternalConnectorType;          ///< The enumeration value from MISC_PORT_CONNECTOR_TYPE.
+  PortTypeAudioPort,                  // PortType;                       ///< The enumeration value from MISC_PORT_TYPE.
+};
+CHAR8               *gSmbiosType8Strings9[] = {
+  "Audio Line Out",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE9  gSmbiosType9Template = {
+  { EFI_SMBIOS_TYPE_SYSTEM_SLOTS, sizeof (SMBIOS_TABLE_TYPE9), 0 },
+  1,                     // SlotDesignation String
+  SlotTypeOther,         // SlotType;                 ///< The enumeration value from MISC_SLOT_TYPE.
+  SlotDataBusWidthOther, // SlotDataBusWidth;         ///< The enumeration value from MISC_SLOT_DATA_BUS_WIDTH.
+  SlotUsageAvailable,    // CurrentUsage;             ///< The enumeration value from MISC_SLOT_USAGE.
+  SlotLengthOther,       // SlotLength;               ///< The enumeration value from MISC_SLOT_LENGTH.
+  0,                     // SlotID;
+  {    // SlotCharacteristics1;
+    1, // CharacteristicsUnknown  :1;
+    0, // Provides50Volts         :1;
+    0, // Provides33Volts         :1;
+    0, // SharedSlot              :1;
+    0, // PcCard16Supported       :1;
+    0, // CardBusSupported        :1;
+    0, // ZoomVideoSupported      :1;
+    0, // ModemRingResumeSupported:1;
+  },
+  {     // SlotCharacteristics2;
+    0,  // PmeSignalSupported      :1;
+    0,  // HotPlugDevicesSupported :1;
+    0,  // SmbusSignalSupported    :1;
+    0,  // Reserved                :5;  ///< Set to 0.
+  },
+  0,    // SegmentGroupNum;
+  0,    // BusNum;
+  0,    // DevFuncNum;
+};
+CHAR8               *gSmbiosType9Strings[] = {
+  "SD Card",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE11  gSmbiosType11Template = {
+  { EFI_SMBIOS_TYPE_OEM_STRINGS, sizeof (SMBIOS_TABLE_TYPE11), 0 },
+  1 // StringCount
+};
+CHAR8                *gSmbiosType11Strings[] = {
+  "OEM Strings: ADVANCED MICRO DEVICES, INC.",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE12  gSmbiosType12Template = {
+  { EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, sizeof (SMBIOS_TABLE_TYPE12), 0 },
+  1 // StringCount
+};
+CHAR8                *gSmbiosType12Strings[] = {
+  "System Configuration Options: SW1-1: Close to Disable On Board Video",
+  NULL
+};
+
+SMBIOS_TABLE_TYPE23  gSmbiosType23Template = {
+  { EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, sizeof (SMBIOS_TABLE_TYPE23), 0 },
+  0,  // Capabilities;
+  0,  // ResetCount;
+  0,  // ResetLimit;
+  0,  // TimerInterval;
+  0   // Timeout;
+};
+
+SMBIOS_TABLE_TYPE32  gSmbiosType32Template = {
+  { EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, sizeof (SMBIOS_TABLE_TYPE32), 0 },
+  { 0,                                       0,                            0, 0, 0, 0}, // Reserved[6];
+  BootInformationStatusNoError                                                  // BootStatus
+};
+
+SMBIOS_TEMPLATE_ENTRY  gSmbiosTemplate[] = {
+  { (SMBIOS_STRUCTURE *)&gSmbiosType0Template,  gSmbiosType0Strings  },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType1Template,  gSmbiosType1Strings  },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType2Template,  gSmbiosType2Strings  },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType3Template,  gSmbiosType3Strings  },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType8Template1, gSmbiosType8Strings1 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType8Template2, gSmbiosType8Strings2 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType8Template3, gSmbiosType8Strings3 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType8Template4, gSmbiosType8Strings4 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType8Template5, gSmbiosType8Strings5 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType8Template6, gSmbiosType8Strings6 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType8Template7, gSmbiosType8Strings7 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType8Template8, gSmbiosType8Strings8 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType8Template9, gSmbiosType8Strings9 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType9Template,  gSmbiosType9Strings  },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType11Template, gSmbiosType11Strings },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType12Template, gSmbiosType12Strings },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType23Template, NULL                 },
+  { (SMBIOS_STRUCTURE *)&gSmbiosType32Template, NULL                 },
+  { NULL,                                       NULL                 }
+};
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114602): https://edk2.groups.io/g/devel/message/114602
Mute This Topic: https://groups.io/mt/103975483/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (25 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 26/32] AMD/VanGoghBoard: Check in Smbios platform dxe drivers Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module Zhai, MingXin (Duke) via groups.io
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial Fsp2WrapperPkg. It is based on BDK 0.0.7.3323 (USP3527X),
  For more information, Please reference FSP_Release_Notes.txt.

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>
---
 .../edk2/Fsp2WrapperPkg/FSP_Release_Notes.txt |    4 +
 .../edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec    |  161 ++
 .../FspWrapperNotifyDxe/FspWrapperNotifyDxe.c |  676 ++++++++
 .../FspWrapperNotifyDxe.inf                   |   75 +
 .../FspWrapperNotifyDxe/LoadBelow4G.c         |  147 ++
 .../FspmWrapperPeim/FspmWrapperPeim.c         |  478 ++++++
 .../FspmWrapperPeim/FspmWrapperPeim.inf       |   92 ++
 .../FspsMultiPhaseSiInitDxe.c                 |  206 +++
 .../FspsMultiPhaseSiInitDxe.inf               |   74 +
 .../FspsMultiPhaseSiInitDxe/LoadBelow4G.c     |  148 ++
 .../FspsWrapperPeim/FspsWrapperPeim.c         |  632 ++++++++
 .../FspsWrapperPeim/FspsWrapperPeim.inf       |   91 ++
 .../Include/FspExportedInterfaceHob.h         |  146 ++
 .../Include/FspMemoryRegionHob.h              |   15 +
 .../Include/FspSmmDataExchangeBuffer.h        |   24 +
 .../edk2/Fsp2WrapperPkg/Include/FspUpd.h      |   23 +
 .../edk2/Fsp2WrapperPkg/Include/FspmUpd.h     |   66 +
 .../edk2/Fsp2WrapperPkg/Include/FspsUpd.h     |   45 +
 .../edk2/Fsp2WrapperPkg/Include/FsptUpd.h     |   18 +
 .../Include/Library/FspMeasurementLib.h       |   41 +
 .../Include/Library/FspWrapperApiLib.h        |   82 +
 .../Include/Library/FspWrapperApiTestLib.h    |   56 +
 .../Include/Library/FspWrapperHobProcessLib.h |   39 +
 .../Library/FspWrapperMultiPhaseProcessLib.h  |   45 +
 .../Include/Library/FspWrapperPlatformLib.h   |   81 +
 .../Library/FspWrapperPlatformMultiPhaseLib.h |   31 +
 .../Include/MultiPhaseSiPhases.h              |   19 +
 .../Include/Ppi/FspSiliconInitDone.h          |   38 +
 .../Include/Ppi/TopOfTemporaryRam.h           |   15 +
 .../BaseFspMeasurementLib.inf                 |   54 +
 .../BaseFspMeasurementLib/FspMeasurementLib.c |  254 +++
 .../BaseFspWrapperApiLib.inf                  |   66 +
 .../BaseFspWrapperApiLib/FspWrapperApiLib.c   |  235 +++
 .../IA32/DispatchExecute.c                    |   71 +
 .../X64/DispatchExecute.c                     |  167 ++
 .../BaseFspWrapperApiLib/X64/Thunk64To32.nasm |  252 +++
 .../BaseFspWrapperApiTestLibNull.inf          |   49 +
 .../FspWrapperApiTestNull.c                   |   60 +
 .../BaseFspWrapperPlatformLibSample.inf       |   72 +
 .../FspWrapperPlatformLibSample.c             |  347 ++++
 ...aseFspWrapperPlatformMultiPhaseLibNull.inf |   37 +
 .../FspWrapperPlatformMultiPhaseLibNull.c     |   51 +
 .../DxeFspWrapperMultiPhaseProcessLib.c       |  531 ++++++
 .../DxeFspWrapperMultiPhaseProcessLib.inf     |   79 +
 .../FspWrapperMultiPhaseProcessLib.inf        |   49 +
 .../PeiFspWrapperMultiPhaseProcessLib.c       |  385 +++++
 .../FspWrapperApiTest.c                       |   85 +
 .../PeiFspWrapperApiTestLib.inf               |   52 +
 .../CommonHeader.h                            |   91 ++
 .../FspWrapperHobProcessLibSample.c           | 1439 +++++++++++++++++
 .../MemoryInstall.h                           |  171 ++
 .../PeiFspWrapperHobProcessLibSample.inf      |  121 ++
 .../SecFspWrapperPlatformSecLibSample/Fsp.h   |   45 +
 .../FspWrapperPlatformSecLibSample.c          |  129 ++
 .../Ia32/PeiCoreEntry.nasm                    |  130 ++
 .../Ia32/SecEntry.nasm                        |  335 ++++
 .../Ia32/Stack.nasm                           |   73 +
 .../PlatformInit.c                            |   38 +
 .../SecFspWrapperPlatformSecLibSample.inf     |   87 +
 .../SecGetPerformance.c                       |   84 +
 .../SecPlatformInformation.c                  |   78 +
 .../SecRamInitData.c                          |   63 +
 .../SecTempRamDone.c                          |   43 +
 .../X64/PeiCoreEntry.nasm                     |  149 ++
 .../X64/SecEntry.nasm                         |  173 ++
 .../X64/Stack.nasm                            |   73 +
 .../PrepareForFspSmmDxe/PrepareForFspSmmDxe.c |  152 ++
 .../PrepareForFspSmmDxe.inf                   |   57 +
 .../PrepareForFspSmmDxeFsp.c                  |   86 +
 .../PrepareForFspSmmDxeFsp.inf                |   49 +
 70 files changed, 10130 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Release_Notes.txt
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/LoadBelow4G.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspExportedInterfaceHob.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspMemoryRegionHob.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspSmmDataExchangeBuffer.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspUpd.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspmUpd.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspsUpd.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FsptUpd.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspMeasurementLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiTestLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperHobProcessLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperMultiPhaseProcessLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformMultiPhaseLib.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/MultiPhaseSiPhases.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/FspSiliconInitDone.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/TopOfTemporaryRam.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/FspMeasurementLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPhaseLibNull.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLibNull.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/FspWrapperApiTest.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/CommonHeader.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/MemoryInstall.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Fsp.h
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/Stack.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/PlatformInit.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecGetPerformance.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecPlatformInformation.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecTempRamDone.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/SecEntry.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/Stack.nasm
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.inf

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Release_Notes.txt b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Release_Notes.txt
new file mode 100644
index 0000000000..92e8f7a43b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Release_Notes.txt
@@ -0,0 +1,4 @@
+***************************************************
+Sephiroth FSP USP3527X     2023-05-27
+***************************************************
+Based on BDK 0.0.7.3323 (USP3527X)
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
new file mode 100644
index 0000000000..74939b9348
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
@@ -0,0 +1,161 @@
+## @file
+# Provides drivers and definitions to support fsp in EDKII bios.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010005
+  PACKAGE_NAME                   = Fsp2WrapperPkg
+  PACKAGE_GUID                   = FAFE06D4-7245-42D7-9FD2-E5D5E36AB0A0
+  PACKAGE_VERSION                = 0.1
+
+[Includes]
+  Include
+
+[LibraryClasses]
+  ##  @libraryclass  Provide FSP API related function.
+  FspWrapperApiLib|Include/Library/FspWrapperApiLib.h
+  FspWrapperApiTestLib|Include/Library/FspWrapperApiTestLib.h
+
+  ##  @libraryclass  Provide FSP hob process related function.
+  FspWrapperHobProcessLib|Include/Library/FspWrapperHobProcessLib.h
+
+  ##  @libraryclass  Provide FSP platform related function.
+  FspWrapperPlatformLib|Include/Library/FspWrapperPlatformLib.h
+
+  ##  @libraryclass  Provide FSP TPM measurement related function.
+  FspMeasurementLib|Include/Library/FspMeasurementLib.h
+
+  ##  @libraryclass  Provide MultiPhase handling related functions.
+  FspWrapperMultiPhaseProcessLib|Include/Library/FspWrapperMultiPhaseProcessLib.h
+
+  ##  @libraryclass  Provide MultiPhase platform actions related functions.
+  FspWrapperPlatformMultiPhaseLib|Include/Library/FspWrapperPlatformMultiPhaseLib.h
+
+
+[Guids]
+  #
+  # GUID defined in package
+  #
+  gIntelFsp2WrapperTokenSpaceGuid       = { 0xa34cf082, 0xf50, 0x4f0d,  { 0x89, 0x8a, 0x3d, 0x39, 0x30, 0x2b, 0xc5, 0x1e } }
+  gFspApiPerformanceGuid                = { 0xc9122295, 0x56ed, 0x4d4e, { 0x06, 0xa6, 0x50, 0x8d, 0x89, 0x4d, 0x3e, 0x40 } }
+  gFspHobGuid                           = { 0x6d86fb36, 0xba90, 0x472c, { 0xb5, 0x83, 0x3f, 0xbe, 0xd3, 0xfb, 0x20, 0x9a } }
+  gAmdFspMemoryUnder1MGuid              = { 0x1b551672, 0xe7cd, 0x4639, { 0xae, 0xc0, 0x5f, 0x55, 0x9c, 0xd5, 0x51, 0x85 }}
+  gFspsUpdDataPointerAddressGuid        = { 0x8fdb4d5e, 0x5309, 0x4940, { 0x9e, 0x4a, 0xa2, 0x9c, 0x8f, 0xac, 0x4d, 0x50 }}
+  gFsp2WrapperTokenSpaceGuid            = { 0x9db7c6aa, 0x8621, 0x43cf, { 0xa1, 0x53, 0xfb, 0xac, 0x5, 0xd, 0x88, 0xcc   } }
+  gAmdFspPkgGuid                        = { 0x1b58cd9a, 0x878f, 0x481c, { 0x83, 0x82, 0x4c, 0xf9, 0x6a, 0x83, 0xc8, 0xfe }}
+  gAmdFspUpdGuid                        = { 0x728d3b7c, 0xfaec, 0x4f77, { 0xb7, 0x84, 0x6b, 0x2, 0x37, 0xf1, 0x1e, 0xa7 } }
+
+
+[Ppis]
+  gFspSiliconInitDonePpiGuid            = { 0x4eb6e09c, 0xd256, 0x4e1e, { 0xb5, 0x0a, 0x87, 0x4b, 0xd2, 0x84, 0xb3, 0xde } }
+  gTopOfTemporaryRamPpiGuid             = { 0x2f3962b2, 0x57c5, 0x44ec, { 0x9e, 0xfc, 0xa6, 0x9f, 0xd3, 0x02, 0x03, 0x2b } }
+
+[Protocols]
+  gAddPerfRecordProtocolGuid            = { 0xc4a58d6d, 0x3677, 0x49cb, { 0xa0, 0x0a, 0x94, 0x70, 0x76, 0x5f, 0xb5, 0x5e } }
+
+################################################################################
+#
+# PCD Declarations section - list of all PCDs Declared by this Package
+#                            Only this package should be providing the
+#                            declaration, other packages should not.
+#
+################################################################################
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+  ## Provides the memory mapped base address of the BIOS CodeCache Flash Device.
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFlashCodeCacheAddress|0xFFE00000|UINT32|0x10000001
+  ## Provides the size of the BIOS Flash Device.
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFlashCodeCacheSize|0x00200000|UINT32|0x10000002
+
+  ## Indicate the PEI memory size platform want to report
+  gIntelFsp2WrapperTokenSpaceGuid.PcdPeiMinMemSize|0x1800000|UINT32|0x40000004
+  ## Indicate the PEI memory size platform want to report
+  gIntelFsp2WrapperTokenSpaceGuid.PcdPeiRecoveryMinMemSize|0x3000000|UINT32|0x40000005
+
+  ## This is the base address of FSP-T
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFsptBaseAddress|0x00000000|UINT32|0x00000300
+
+  ## This PCD indicates if FSP APIs are skipped from FSP wrapper.<BR><BR>
+  #  If a bit is set, that means this FSP API is skipped.<BR>
+  #  If a bit is clear, that means this FSP API is NOT skipped.<BR>
+  #  NOTE: Only NotifyPhase Post PCI enumeration (BIT16) is implemented.<BR>
+  #  BIT[15:0] is for function:<BR>
+  #    BIT0    - Skip TempRamInit<BR>
+  #    BIT1    - Skip MemoryInit<BR>
+  #    BIT2    - Skip TempRamExit<BR>
+  #    BIT3    - Skip SiliconInit<BR>
+  #    BIT4    - Skip NotifyPhase<BR>
+  #  BIT[32:16] is for sub-function:<BR>
+  #    BIT16   - Skip NotifyPhase (AfterPciEnumeration)<BR>
+  #    BIT17   - Skip NotifyPhase (ReadyToBoot)<BR>
+  #    BIT18   - Skip NotifyPhase (EndOfFirmware)<BR>
+  #  Any undefined BITs are reserved for future use.<BR>
+  # @Prompt Skip FSP API from FSP wrapper.
+  gIntelFsp2WrapperTokenSpaceGuid.PcdSkipFspApi|0x00000000|UINT32|0x40000009
+
+  ## This PCD decides how FSP is measured
+  # 1) The BootGuard ACM may already measured the FSP component, such as FSPT/FSPM.
+  # We need a flag (PCD) to indicate if there is need to do such FSP measurement or NOT.
+  # 2) The FSP binary includes FSP code and FSP UPD region. The UPD region is considered
+  # as configuration block, and it may be updated by OEM by design.
+  # This flag (PCD) is to indicate if we need isolate the UPD region from the FSP code region.
+  # BIT0: Need measure FSP. (for FSP1.x) - reserved in FSP2.
+  # BIT1: Need measure FSPT. (for FSP 2.x)
+  # BIT2: Need measure FSPM. (for FSP 2.x)
+  # BIT3: Need measure FSPS. (for FSP 2.x)
+  # BIT4~30: reserved.
+  # BIT31: Need isolate UPD region measurement.
+    #0: measure FSP[T|M|S] as one binary in one record (PCR0).
+    #1: measure FSP UPD region in one record (PCR1), the FSP code without UPD in another record (PCR0).
+  #
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig|0x00000000|UINT32|0x4000000B
+
+[PcdsFixedAtBuild, PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx]
+  ## This PCD decides how Wrapper code utilizes FSP
+  # 0: DISPATCH mode (FSP Wrapper will load PeiCore from FSP without calling FSP API)
+  # 1: API mode (FSP Wrapper will call FSP API)
+  #
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection|0x00000001|UINT8|0x4000000A
+
+  #
+  ## These are the base address of FSP-M/S
+  #
+  gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInFlash|0x00000000|UINT32|0x00001000
+  gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInFlash|0x00000000|UINT32|0x00001001
+  gFsp2WrapperTokenSpaceGuid.PcdFspoPeiBaseAddressInFlash|0x00000000|UINT32|0x00001002
+  gFsp2WrapperTokenSpaceGuid.PcdFspoDxeBaseAddressInFlash|0x00000000|UINT32|0x00001003
+
+  gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInMemory|0x00000000|UINT32|0x00002000
+  gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInMemory|0x00000000|UINT32|0x00002001
+  gFsp2WrapperTokenSpaceGuid.PcdFspoPeiBaseAddressInMemory|0x00000000|UINT32|0x00002002
+  gFsp2WrapperTokenSpaceGuid.PcdFspoDxeBaseAddressInMemory|0x00000000|UINT32|0x00002003
+
+  gFsp2WrapperTokenSpaceGuid.PcdFspmRegionSize|0x00000000|UINT32|0x00003000
+  gFsp2WrapperTokenSpaceGuid.PcdFspsRegionSize|0x00000000|UINT32|0x00003001
+  gFsp2WrapperTokenSpaceGuid.PcdFspoPeiRegionSize|0x00000000|UINT32|0x00003002
+  gFsp2WrapperTokenSpaceGuid.PcdFspoDxeRegionSize|0x00000000|UINT32|0x00003003
+
+  gFsp2WrapperTokenSpaceGuid.FspoPeiWorkaroundShadowCopyAddress|0x09E00000|UINT32|0x18000005
+
+  #
+  # To provide flexibility for platform to pre-allocate FSP UPD buffer
+  #
+  # The PCDs define the pre-allocated FSPM and FSPS UPD Data Buffer Address.
+  # 0x00000000 - Platform will not pre-allocate UPD buffer before FspWrapper module
+  # non-zero   - Platform will pre-allocate UPD buffer and patch this value to
+  #              buffer address before FspWrapper module executing.
+  #
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress|0x00000000|UINT32|0x50000000
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress|0x00000000|UINT32|0x50000001
+  #
+  # Non-0 means PcdFspmUpdDataAddress will be ignored, otherwise PcdFspmUpdDataAddress will be used.
+  #
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress64|0x00000000|UINT64|0x50000002
+  #
+  # Non-0 means PcdFspsUpdDataAddress will be ignored, otherwise PcdFspsUpdDataAddress will be used.
+  #
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress64|0x00000000|UINT64|0x50000003
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.c
new file mode 100644
index 0000000000..0c997b40d0
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.c
@@ -0,0 +1,676 @@
+/** @file
+  This driver will register two callbacks to call fsp's notifies.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Protocol/PciEnumerationComplete.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/HobLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Protocol/AcpiSystemDescriptionTable.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/Timer.h>
+#include <Protocol/PciIo.h>
+#include <FspsUpd.h>
+#include <FspMemoryRegionHob.h>
+#include <FspExportedInterfaceHob.h>
+#include <FspStatusCode.h>
+#include <Library/MemoryAllocationLib.h>
+
+#define   FSP_API_NOTIFY_PHASE_AFTER_PCI_ENUMERATION  BIT16
+extern EFI_GUID  gFspsUpdDataPointerAddressGuid;
+extern EFI_GUID  gFspReservedMemoryResourceHobGuid;
+extern EFI_GUID  gEfiEventExitBootServicesGuid;
+extern EFI_GUID  gEfiEventVirtualAddressChangeGuid;
+extern EFI_GUID  gEfiPciIoProtocolGuid;
+
+FSPS_UPD *volatile                   FspsUpd;
+FSPS_UPD *volatile                   FspsUpdInRt;
+volatile FSP_EXPORTED_INTERFACE_HOB  *ExportedInterfaceHob;
+typedef
+EFI_STATUS
+(EFIAPI *ADD_PERFORMANCE_RECORDS)(
+  IN CONST VOID *HobStart
+  );
+
+struct _ADD_PERFORMANCE_RECORD_PROTOCOL {
+  ADD_PERFORMANCE_RECORDS    AddPerformanceRecords;
+};
+
+typedef struct _ADD_PERFORMANCE_RECORD_PROTOCOL ADD_PERFORMANCE_RECORD_PROTOCOL;
+
+extern EFI_GUID  gAddPerfRecordProtocolGuid;
+extern EFI_GUID  gFspHobGuid;
+extern EFI_GUID  gFspApiPerformanceGuid;
+
+static EFI_EVENT  mExitBootServicesEvent     = NULL;
+static EFI_EVENT  mVirtualAddressChangeEvent = NULL;
+
+/**
+  Relocate this image under 4G memory.
+
+  @param  ImageHandle  Handle of driver image.
+  @param  SystemTable  Pointer to system table.
+
+  @retval EFI_SUCCESS  Image successfully relocated.
+  @retval EFI_ABORTED  Failed to relocate image.
+
+**/
+EFI_STATUS
+RelocateImageUnder4GIfNeeded (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+/**
+ * For some reason, the FSP MAY enable the interrupt after processing SMM,
+ * which is not ideal because this MAY cause timer interrupt being fired during FSP.
+ *
+ * A workaround is to disable timer shortly, and re-enable it after FSP call.
+**/
+
+STATIC EFI_TIMER_ARCH_PROTOCOL  *gTimer        = NULL;
+STATIC UINT64                   mTimerInterval = 0;
+
+VOID
+EFIAPI
+DisableTimer (
+  VOID
+  )
+{
+  EFI_STATUS  Status = gTimer->GetTimerPeriod (gTimer, &mTimerInterval);
+
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "FSP TimerWorkaround begin: Timer interval val %llx\n", mTimerInterval));
+  }
+
+  Status = gTimer->SetTimerPeriod (gTimer, 0);
+  ASSERT_EFI_ERROR (Status);
+}
+
+VOID
+EFIAPI
+EnableTimer (
+  VOID
+  )
+{
+  DEBUG ((DEBUG_INFO, "FSP TimerWorkaround end: Timer interval val %llx\n", mTimerInterval));
+  EFI_STATUS  Status = EFI_SUCCESS;
+
+  if (mTimerInterval != 0) {
+    Status = gTimer->SetTimerPeriod (gTimer, mTimerInterval);
+  }
+
+  ASSERT_EFI_ERROR (Status);
+}
+
+/**
+  PciEnumerationComplete Protocol notification event handler.
+
+  @param[in] Event    Event whose notification function is being invoked.
+  @param[in] Context  Pointer to the notification function's context.
+**/
+VOID
+EFIAPI
+OnPciEnumerationComplete (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  NOTIFY_PHASE_PARAMS  NotifyPhaseParams;
+  EFI_STATUS           Status;
+  VOID                 *Interface;
+
+  //
+  // Try to locate it because gEfiPciEnumerationCompleteProtocolGuid will trigger it once when registration.
+  // Just return if it is not found.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiPciEnumerationCompleteProtocolGuid,
+                  NULL,
+                  &Interface
+                  );
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  NotifyPhaseParams.Phase = EnumInitPhaseAfterPciEnumeration;
+  EFI_HANDLE  *Handles      = NULL;
+  VOID        *Protocol     = NULL;
+  UINTN       ProtocolCount = 0;
+
+  gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &ProtocolCount, &Handles);
+  EFI_PCI_IO_PROTOCOL  **Protocols = AllocateZeroPool (sizeof (VOID *)*ProtocolCount);
+
+  for (UINT64 i = 0; i < ProtocolCount; i++) {
+    DEBUG ((DEBUG_INFO, "FSP-S Wrapper: Getting PCI Protocol %d/%d\n", i, ProtocolCount));
+    gBS->HandleProtocol (Handles[i], &gEfiPciIoProtocolGuid, &Protocol);
+    Protocols[i] = Protocol;
+  }
+
+  DEBUG ((DEBUG_ERROR, " ExportedInterfaceHob:%011p\n", ExportedInterfaceHob));
+  // gBS->LocateProtocol(&gEfiPciIoProtocolGuid,NULL,&Protocol);
+  ExportedInterfaceHob->EfiPciIoProtocol      = Protocols;
+  ExportedInterfaceHob->EfiPciIoProtocolCount = ProtocolCount;
+  PERF_START_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+  DisableTimer ();
+  Status = CallFspNotifyPhase (&NotifyPhaseParams);
+  EnableTimer ();
+  PERF_END_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+
+  //
+  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+  //
+  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+    DEBUG ((DEBUG_INFO, "FSP NotifyPhase AfterPciEnumeration requested reset 0x%x\n", Status));
+    CallFspWrapperResetSystem (Status);
+  }
+
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "FSP NotifyPhase AfterPciEnumeration failed, status: 0x%x\n", Status));
+  } else {
+    DEBUG ((DEBUG_INFO, "FSP NotifyPhase AfterPciEnumeration Success.\n"));
+  }
+}
+
+STATIC
+VOID
+ReportFspMemoryUsage (
+  VOID
+  )
+{
+  FSP_MEMORY_REGION_HOB  *MemoryRegionHob = NULL;
+  EFI_STATUS             Status;
+
+  DEBUG ((DEBUG_ERROR, " ExportedInterfaceHob:%011p\n", ExportedInterfaceHob));
+  DEBUG ((
+    DEBUG_INFO,
+    "FSP Memory Map Size:%llx,Memory Descriptor Size:%llx:\n",
+    ExportedInterfaceHob->FinalMemoryMapSize,
+    ExportedInterfaceHob->FinalMemoryDescriptorSize
+    ));
+  DEBUG ((DEBUG_INFO, "FSP Memory usage:\n"));
+  UINTN  MemoryDescriptorEntries = ExportedInterfaceHob->FinalMemoryMapSize / \
+                                   ExportedInterfaceHob->FinalMemoryDescriptorSize;
+  EFI_MEMORY_DESCRIPTOR  *FspMemoryDescriptor = ExportedInterfaceHob->FinalMemoryMap;
+  // Now we find the FSP memory HOB, "Free" it, and "Allocate" the memory as its layout in FSP.
+  VOID  *FspHob = GetFirstGuidHob (&gFspReservedMemoryResourceHobGuid);
+
+  if (FspHob != NULL) {
+    MemoryRegionHob = GET_GUID_HOB_DATA (FspHob);
+  }
+
+  if (!MemoryRegionHob) {
+    DEBUG ((DEBUG_ERROR, "Cannot find FSP HOB!\n"));
+    ASSERT ((FALSE));
+    return;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "FSP memory region:0x%08p~0x%08p\n",
+    MemoryRegionHob->BeginAddress, \
+    MemoryRegionHob->BeginAddress+MemoryRegionHob->Length
+    ));
+  // Free previously reserved explicitly for EDK memory recycle.
+  EFI_PHYSICAL_ADDRESS  ReservedMemoryAddress = MemoryRegionHob->BeginAddress+MemoryRegionHob->Length-(10<<EFI_PAGE_SHIFT);
+
+  // Atomic code begins here
+  gBS->RaiseTPL (TPL_NOTIFY);
+  DEBUG ((DEBUG_INFO, "Address    Pages      Type\n"));
+  // Reverse iteration due to EDK's memory allocation method.
+  FspMemoryDescriptor = (EFI_MEMORY_DESCRIPTOR *)((UINTN)FspMemoryDescriptor+ExportedInterfaceHob->FinalMemoryDescriptorSize*(MemoryDescriptorEntries-1));
+  for (UINTN i = 0; i < MemoryDescriptorEntries; i++) {
+    DEBUG ((
+      DEBUG_INFO,
+      "0x%08p 0x%08p %x\n",
+      FspMemoryDescriptor->PhysicalStart, \
+      FspMemoryDescriptor->NumberOfPages,
+      FspMemoryDescriptor->Type
+      ));
+    if (FspMemoryDescriptor->PhysicalStart == ReservedMemoryAddress) {
+      gBS->FreePages (ReservedMemoryAddress, FspMemoryDescriptor->NumberOfPages);
+      FspMemoryDescriptor = (EFI_MEMORY_DESCRIPTOR *)((UINTN)FspMemoryDescriptor-ExportedInterfaceHob->FinalMemoryDescriptorSize);
+      continue;
+    }
+
+    if (FspMemoryDescriptor->Type == EfiMemoryMappedIO) {
+      EFI_GCD_MEMORY_SPACE_DESCRIPTOR  GcdMemorySpaceDescriptor;
+      Status = gDS->GetMemorySpaceDescriptor (FspMemoryDescriptor->PhysicalStart, &GcdMemorySpaceDescriptor);
+      if (!EFI_ERROR (Status)) {
+        if (GcdMemorySpaceDescriptor.GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+          Status = gDS->AddMemorySpace (
+                          EfiGcdMemoryTypeMemoryMappedIo,
+                          FspMemoryDescriptor->PhysicalStart,
+                          FspMemoryDescriptor->NumberOfPages<<EFI_PAGE_SHIFT,
+                          EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
+                          );
+          if (!EFI_ERROR (Status)) {
+            Status = gDS->AllocateMemorySpace (
+                            EfiGcdAllocateAddress,
+                            EfiGcdMemoryTypeMemoryMappedIo,
+                            12,
+                            FspMemoryDescriptor->NumberOfPages<<EFI_PAGE_SHIFT,
+                            &FspMemoryDescriptor->PhysicalStart,
+                            gImageHandle,
+                            NULL
+                            );
+            if (!EFI_ERROR (Status)) {
+              Status = gDS->GetMemorySpaceDescriptor (FspMemoryDescriptor->PhysicalStart, &GcdMemorySpaceDescriptor);
+            }
+          }
+        }
+      }
+
+      // Attempt to set runtime attribute
+      if (!EFI_ERROR (Status)) {
+        if (GcdMemorySpaceDescriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
+          UINT64  Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME | EFI_MEMORY_UC;
+          Status = gDS->SetMemorySpaceAttributes (
+                          FspMemoryDescriptor->PhysicalStart,
+                          FspMemoryDescriptor->NumberOfPages<<EFI_PAGE_SHIFT,
+                          Attributes
+                          );
+        }
+      }
+
+      if (EFI_ERROR (Status)) {
+        DEBUG ((
+          DEBUG_ERROR,
+          "MMIO Region 0x%08p~0x%08p cannot be reserved as RT.\n", \
+          FspMemoryDescriptor->PhysicalStart, \
+          (FspMemoryDescriptor->PhysicalStart+(FspMemoryDescriptor->NumberOfPages<<EFI_PAGE_SHIFT))
+          ));
+        ASSERT (FALSE);
+      }
+
+      DEBUG ((
+        DEBUG_ERROR,
+        "MMIO Region 0x%08p~0x%08p is reserved as RT.\n", \
+        FspMemoryDescriptor->PhysicalStart, \
+        (FspMemoryDescriptor->PhysicalStart+(FspMemoryDescriptor->NumberOfPages<<EFI_PAGE_SHIFT))
+        ));
+    } else {
+      if (  (FspMemoryDescriptor->PhysicalStart >= MemoryRegionHob->BeginAddress)
+         && ((FspMemoryDescriptor->PhysicalStart+(FspMemoryDescriptor->NumberOfPages<<EFI_PAGE_SHIFT)) <= (MemoryRegionHob->BeginAddress+MemoryRegionHob->Length)))
+      {
+        Status = gBS->FreePages (FspMemoryDescriptor->PhysicalStart, FspMemoryDescriptor->NumberOfPages);
+        ASSERT (Status == EFI_SUCCESS);
+        if (FspMemoryDescriptor->Type != EfiConventionalMemory) {
+          Status = gBS->AllocatePages (AllocateAddress, FspMemoryDescriptor->Type, FspMemoryDescriptor->NumberOfPages, &FspMemoryDescriptor->PhysicalStart);
+          ASSERT (Status == EFI_SUCCESS);
+        } else {
+          DEBUG ((
+            DEBUG_ERROR,
+            "Address 0x%08p~0x%08p is free\n", \
+            FspMemoryDescriptor->PhysicalStart, \
+            (FspMemoryDescriptor->PhysicalStart+(FspMemoryDescriptor->NumberOfPages<<EFI_PAGE_SHIFT))
+            ));
+        }
+      } else {
+        DEBUG ((
+          DEBUG_ERROR,
+          "Address 0x%08p~0x%08p out of range\n", \
+          FspMemoryDescriptor->PhysicalStart, \
+          (FspMemoryDescriptor->PhysicalStart+(FspMemoryDescriptor->NumberOfPages<<EFI_PAGE_SHIFT))
+          ));
+      }
+    }
+
+    FspMemoryDescriptor = (EFI_MEMORY_DESCRIPTOR *)((UINTN)FspMemoryDescriptor-ExportedInterfaceHob->FinalMemoryDescriptorSize);
+  }
+
+  // Atomic code ends here
+  gBS->RestoreTPL (TPL_CALLBACK);
+}
+
+/**
+  Notification function of EVT_GROUP_READY_TO_BOOT event group.
+
+  This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.
+  When the Boot Manager is about to load and execute a boot option, it reclaims variable
+  storage if free size is below the threshold.
+
+  @param[in] Event        Event whose notification function is being invoked.
+  @param[in] Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+OnReadyToBoot (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  NOTIFY_PHASE_PARAMS  NotifyPhaseParams;
+  EFI_STATUS           Status;
+
+  NotifyPhaseParams.Phase = EnumInitPhaseReadyToBoot;
+  PERF_START_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+  DisableTimer ();
+  Status = CallFspNotifyPhase (&NotifyPhaseParams);
+  EnableTimer ();
+  PERF_END_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+
+  //
+  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+  //
+  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+    DEBUG ((DEBUG_INFO, "FSP NotifyPhase ReadyToBoot requested reset 0x%x\n", Status));
+    CallFspWrapperResetSystem (Status);
+  }
+
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "FSP NotifyPhase ReadyToBoot failed, status: 0x%x\n", Status));
+  } else {
+    DEBUG ((DEBUG_INFO, "FSP NotifyPhase ReadyToBoot Success.\n"));
+    // Now we install ACPI Tables.
+    EFI_ACPI_TABLE_PROTOCOL  *AcpiTableProtocol = NULL;
+    VOID                     *FspsUpdHob        = GetFirstGuidHob (&gFspsUpdDataPointerAddressGuid);
+    if ( FspsUpdHob != NULL ) {
+      FspsUpd = ((FSPS_UPD *)(UINTN)(*(UINT32 *)GET_GUID_HOB_DATA (FspsUpdHob)));
+      Status  = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);
+      if (!EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_INFO, "%a:FSP-S UPD Ptr:%x\n", __FUNCTION__, FspsUpd));
+        UINTN  TableKey = 0;
+        if (ExportedInterfaceHob->AcpiTpm2Table != 0) {
+          DEBUG ((DEBUG_INFO, "TPM2 Table: %x\n", ExportedInterfaceHob->AcpiTpm2Table));
+          Status |= AcpiTableProtocol->InstallAcpiTable (
+                                         AcpiTableProtocol,
+                                         (VOID *)(UINTN)(ExportedInterfaceHob->AcpiTpm2Table),
+                                         ((EFI_ACPI_SDT_HEADER *)(UINTN)(ExportedInterfaceHob->AcpiTpm2Table))->Length,
+                                         &TableKey
+                                         );
+        }
+
+        if (ExportedInterfaceHob->AcpiCratTable != 0) {
+          DEBUG ((DEBUG_INFO, "CRAT Table: %x\n", ExportedInterfaceHob->AcpiCratTable));
+          Status |= AcpiTableProtocol->InstallAcpiTable (
+                                         AcpiTableProtocol,
+                                         (VOID *)(UINTN)(ExportedInterfaceHob->AcpiCratTable),
+                                         ((EFI_ACPI_SDT_HEADER *)(UINTN)(ExportedInterfaceHob->AcpiCratTable))->Length,
+                                         &TableKey
+                                         );
+        }
+
+        if (ExportedInterfaceHob->AcpiCditTable != 0) {
+          DEBUG ((DEBUG_INFO, "CDIT Table: %x\n", ExportedInterfaceHob->AcpiCditTable));
+          Status |= AcpiTableProtocol->InstallAcpiTable (
+                                         AcpiTableProtocol,
+                                         (VOID *)(UINTN)(ExportedInterfaceHob->AcpiCditTable),
+                                         ((EFI_ACPI_SDT_HEADER *)(UINTN)(ExportedInterfaceHob->AcpiCditTable))->Length,
+                                         &TableKey
+                                         );
+        }
+
+        if (ExportedInterfaceHob->AcpiIvrsTable != 0) {
+          DEBUG ((DEBUG_INFO, "IVRS Table: %x\n", ExportedInterfaceHob->AcpiIvrsTable));
+          Status |= AcpiTableProtocol->InstallAcpiTable (
+                                         AcpiTableProtocol,
+                                         (VOID *)(UINTN)(ExportedInterfaceHob->AcpiIvrsTable),
+                                         ((EFI_ACPI_SDT_HEADER *)(UINTN)(ExportedInterfaceHob->AcpiIvrsTable))->Length,
+                                         &TableKey
+                                         );
+        }
+
+        for (int i = 0; i < MAX_ACPI_SSDT_TABLE_COUNT; i++) {
+          if (ExportedInterfaceHob->AcpiSsdtTables[i] != 0) {
+            DEBUG ((DEBUG_INFO, "SSDT Table #%d: %x\n", i, ExportedInterfaceHob->AcpiSsdtTables[i]));
+            Status |= AcpiTableProtocol->InstallAcpiTable (
+                                           AcpiTableProtocol,
+                                           (VOID *)(UINTN)(ExportedInterfaceHob->AcpiSsdtTables[i]),
+                                           ((EFI_ACPI_SDT_HEADER *)(UINTN)(ExportedInterfaceHob->AcpiSsdtTables[i]))->Length,
+                                           &TableKey
+                                           );
+          }
+        }
+      }
+    }
+
+    ReportFspMemoryUsage ();
+  }
+
+  gBS->CloseEvent (Event);
+}
+
+VOID *
+EFIAPI
+ConvertPointer (
+  VOID  *In
+  )
+{
+  if (gRT->ConvertPointer (0, &In) == EFI_SUCCESS) {
+    return In;
+  }
+
+  return NULL;
+}
+
+VOID
+EFIAPI
+OnVirtualAddressChange (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  typedef VOID (EFIAPI *FSP_VIRTUAL_ADDRESS_CHANGE_CALLBACK)(FSPS_UPD *NewUpdAddress);
+  FSP_VIRTUAL_ADDRESS_CHANGE_CALLBACK  VirtualAddressChangeCallback;
+
+  // VOID *VirtualAddressChangeCallbackAddress;
+  // First, we convert the FSP UPD Address.
+  Status = gRT->ConvertPointer (0, (VOID **)&FspsUpdInRt);
+  ASSERT (Status == EFI_SUCCESS);
+  FspsUpd                              = (FSPS_UPD *)FspsUpdInRt;
+  ExportedInterfaceHob->ConvertPointer = ConvertPointer;
+  VirtualAddressChangeCallback         = ExportedInterfaceHob->VirtualAddressChangeCallback;
+  VirtualAddressChangeCallback (FspsUpdInRt);
+  return;
+}
+
+/**
+  This stage is notified just before the firmware/Preboot environment transfers
+  management of all system resources to the OS or next level execution environment.
+
+  @param  Event         Event whose notification function is being invoked.
+  @param  Context       Pointer to the notification function's context, which is
+                        always zero in current implementation.
+
+**/
+VOID
+EFIAPI
+OnEndOfFirmware (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  NOTIFY_PHASE_PARAMS              NotifyPhaseParams;
+  EFI_STATUS                       Status;
+  ADD_PERFORMANCE_RECORD_PROTOCOL  *AddPerfRecordInterface;
+  EFI_PEI_HOB_POINTERS             Hob;
+  VOID                             **FspHobListPtr;
+
+  gBS->CloseEvent (Event);
+  // The FSP UPD is meant to be used in UEFI RT mode.
+  // For this reason, we MUST copy the UPD to RT Memory region.
+  DEBUG ((DEBUG_ERROR, "Copy :%p<->%p\n", FspsUpd, FspsUpdInRt));
+  CopyMem (FspsUpdInRt, FspsUpd, sizeof (FSPS_UPD));
+  NotifyPhaseParams.Phase = EnumInitPhaseEndOfFirmware;
+  PERF_START_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+  DisableTimer ();
+  Status = CallFspNotifyPhase (&NotifyPhaseParams);
+  EnableTimer ();
+  PERF_END_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+
+  //
+  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+  //
+  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+    DEBUG ((DEBUG_INFO, "FSP NotifyPhase EndOfFirmware requested reset 0x%x\n", Status));
+    CallFspWrapperResetSystem (Status);
+  }
+
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "FSP NotifyPhase EndOfFirmware failed, status: 0x%x\n", Status));
+  } else {
+    DEBUG ((DEBUG_INFO, "FSP NotifyPhase EndOfFirmware Success.\n"));
+  }
+
+  // Add the FSP interface here.
+  ExportedInterfaceHob->ConvertPointer = ConvertPointer;
+  Status                               = gBS->LocateProtocol (
+                                                &gAddPerfRecordProtocolGuid,
+                                                NULL,
+                                                (VOID **)&AddPerfRecordInterface
+                                                );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "gAddPerfRecordProtocolGuid - Locate protocol failed\n"));
+    return;
+  } else {
+    Hob.Raw = GetFirstGuidHob (&gFspHobGuid);
+    if (Hob.Raw != NULL) {
+      FspHobListPtr = GET_GUID_HOB_DATA (Hob.Raw);
+      AddPerfRecordInterface->AddPerformanceRecords ((VOID *)(UINTN)(((UINT32)(UINTN)*FspHobListPtr) & 0xFFFFFFFF));
+    }
+  }
+}
+
+STATIC
+VOID *
+GetFspHobList (
+  VOID
+  )
+{
+  EFI_HOB_GUID_TYPE  *GuidHob;
+
+  GuidHob = GetFirstGuidHob (&gFspHobGuid);
+  if (GuidHob != NULL) {
+    return *(VOID **)GET_GUID_HOB_DATA (GuidHob);
+  } else {
+    return NULL;
+  }
+}
+
+/**
+  Main entry for the FSP DXE module.
+
+  This routine registers two callbacks to call fsp's notifies.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+FspWrapperNotifyDxeEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_EVENT   ReadyToBootEvent;
+  VOID        *Registration;
+  EFI_EVENT   ProtocolNotifyEvent;
+  UINT32      FspApiMask;
+
+  if (!PcdGet8 (PcdFspModeSelection)) {
+    // Dispatch Mode
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Load this driver's image to memory
+  //
+  Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable);
+  if (EFI_ERROR (Status)) {
+    return EFI_SUCCESS;
+  }
+
+  FspApiMask = PcdGet32 (PcdSkipFspApi);
+  if ((FspApiMask & FSP_API_NOTIFY_PHASE_AFTER_PCI_ENUMERATION) == 0) {
+    ProtocolNotifyEvent = EfiCreateProtocolNotifyEvent (
+                            &gEfiPciEnumerationCompleteProtocolGuid,
+                            TPL_CALLBACK,
+                            OnPciEnumerationComplete,
+                            NULL,
+                            &Registration
+                            );
+    ASSERT (ProtocolNotifyEvent != NULL);
+  }
+
+  Status = EfiCreateEventReadyToBootEx (
+             TPL_CALLBACK,
+             OnReadyToBoot,
+             NULL,
+             &ReadyToBootEvent
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  OnEndOfFirmware,
+                  NULL,
+                  &gEfiEventExitBootServicesGuid,
+                  &mExitBootServicesEvent
+                  );
+
+  gBS->CreateEventEx (
+         EVT_NOTIFY_SIGNAL,
+         TPL_NOTIFY,
+         OnVirtualAddressChange,
+         NULL,
+         &gEfiEventVirtualAddressChangeGuid,
+         &mVirtualAddressChangeEvent
+         );
+  ASSERT_EFI_ERROR (Status);
+  // The FSP UPD is meant to be used in UEFI RT mode.
+  // For this reason, we MUST copy the UPD to RT Memory region.
+  Status = gBS->AllocatePool (EfiRuntimeServicesData, sizeof (FSPS_UPD), (VOID **)&FspsUpdInRt);
+  ASSERT ((Status == EFI_SUCCESS));
+  Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **)&gTimer);
+  ASSERT ((Status == EFI_SUCCESS));
+  VOID  *ExportedInterfaceRawHob = GetNextGuidHob (&gFspExportedInterfaceHobGuid, (VOID *)((UINTN)GetFspHobList ()&0xFFFFFFFF));
+
+  DEBUG ((DEBUG_ERROR, " ExportedInterfaceRawHob:%011p\n", ExportedInterfaceRawHob));
+  if ( ExportedInterfaceRawHob != NULL) {
+    ExportedInterfaceHob = GET_GUID_HOB_DATA (ExportedInterfaceRawHob);
+    DEBUG ((DEBUG_ERROR, " ExportedInterfaceHob:%011p\n", ExportedInterfaceHob));
+    ExportedInterfaceHob = ExportedInterfaceHob->ExportedInterfaceHobAddressAfterNotifyPhase;
+    DEBUG ((DEBUG_ERROR, "New ExportedInterfaceHob:%011p\n", ExportedInterfaceHob));
+  }
+
+  return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+CallFspWrapperResetSystem (
+  IN EFI_STATUS  FspStatusResetType
+  )
+{
+  //
+  // Perform reset according to the type.
+  //
+
+  CpuDeadLoop ();
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf
new file mode 100644
index 0000000000..03369890fa
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf
@@ -0,0 +1,75 @@
+## @file
+# FSP DXE Module
+#
+# This driver will register two callbacks to call fsp's notifies.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FspWrapperNotifyDxe
+  FILE_GUID                      = AD61999A-507E-47E6-BA28-79CC609FA1A4
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = FspWrapperNotifyDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  FspWrapperNotifyDxe.c
+  LoadBelow4G.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  ChachaniBoardPkg/Project.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  DxeServicesTableLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  DebugLib
+  BaseMemoryLib
+  UefiLib
+  FspWrapperApiLib
+  PeCoffLib
+  CacheMaintenanceLib
+  DxeServicesLib
+  PerformanceLib
+  HobLib
+  UefiRuntimeLib
+
+[Protocols]
+  gEfiPciEnumerationCompleteProtocolGuid            ## CONSUMES
+  gAddPerfRecordProtocolGuid                        ## SOMETIMES_CONSUMES
+  gEfiAcpiTableProtocolGuid                         ## CONSUMES  FOR_ACPI
+  gEfiTimerArchProtocolGuid                         ## CONSUMES  FOR_INTERRUPT_WORKAROUND
+  gEfiPciIoProtocolGuid                             ## CONSUMES  FOR_FSP
+
+[Guids]
+  gFspApiPerformanceGuid                            ## SOMETIMES_CONSUMES ## GUID
+  gEfiEventExitBootServicesGuid                     ## CONSUMES ## Event
+  gFspHobGuid                                       ## CONSUMES ## HOB
+  gFspsUpdDataPointerAddressGuid                    ## CONSUMES  FOR_HOB
+  gEfiEventVirtualAddressChangeGuid                 ## CONSUMES  FOR FSP_RT
+  gFspReservedMemoryResourceHobGuid                 ## CONSUMES  FOR FSP_MEMORY_REPORT
+  gFspExportedInterfaceHobGuid                      ## CONSUMES  FOR EXPORTED_INTERFACE
+
+[Pcd]
+  gIntelFsp2WrapperTokenSpaceGuid.PcdSkipFspApi       ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection
+[Depex]
+  gEfiTimerArchProtocolGuid AND gFspSmmDependencyReadyProtocolGuid
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c
new file mode 100644
index 0000000000..9a49d3b492
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/LoadBelow4G.c
@@ -0,0 +1,147 @@
+/** @file
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/UefiLib.h>
+
+/**
+  Relocate this image under 4G memory.
+
+  @param  ImageHandle  Handle of driver image.
+  @param  SystemTable  Pointer to system table.
+
+  @retval EFI_SUCCESS  Image successfully relocated.
+  @retval EFI_ABORTED  Failed to relocate image.
+
+**/
+EFI_STATUS
+RelocateImageUnder4GIfNeeded (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                    Status;
+  UINT8                         *Buffer;
+  UINTN                         BufferSize;
+  EFI_HANDLE                    NewImageHandle;
+  UINTN                         Pages;
+  EFI_PHYSICAL_ADDRESS          FfsBuffer;
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  VOID                          *Interface;
+
+  //
+  // If it is already <4G, no need do relocate
+  //
+  if ((UINTN)RelocateImageUnder4GIfNeeded < 0xFFFFFFFF) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // If locate gEfiCallerIdGuid success, it means 2nd entry.
+  //
+  Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &Interface);
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "FspNotifyDxe - 2nd entry\n"));
+    return EFI_SUCCESS;
+  }
+
+  DEBUG ((DEBUG_INFO, "FspNotifyDxe - 1st entry\n"));
+
+  //
+  // Here we install a dummy handle
+  //
+  NewImageHandle = NULL;
+  Status         = gBS->InstallProtocolInterface (
+                          &NewImageHandle,
+                          &gEfiCallerIdGuid,
+                          EFI_NATIVE_INTERFACE,
+                          NULL
+                          );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Reload image itself to <4G mem
+  //
+  Status = GetSectionFromAnyFv (
+             &gEfiCallerIdGuid,
+             EFI_SECTION_PE32,
+             0,
+             (VOID **)&Buffer,
+             &BufferSize
+             );
+  ASSERT_EFI_ERROR (Status);
+  ImageContext.Handle    = Buffer;
+  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+  //
+  // Get information about the image being loaded
+  //
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
+  if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
+    Pages = EFI_SIZE_TO_PAGES ((UINTN)(ImageContext.ImageSize + ImageContext.SectionAlignment));
+  } else {
+    Pages = EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize);
+  }
+
+  FfsBuffer = 0xFFFFFFFF;
+  Status    = gBS->AllocatePages (
+                     AllocateMaxAddress,
+                     EfiBootServicesCode,
+                     Pages,
+                     &FfsBuffer
+                     );
+  ASSERT_EFI_ERROR (Status);
+  ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
+  //
+  // Align buffer on section boundary
+  //
+  ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
+  //
+  // Load the image to our new buffer
+  //
+  Status = PeCoffLoaderLoadImage (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Relocate the image in our new buffer
+  //
+  Status = PeCoffLoaderRelocateImage (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
+  //
+  gBS->FreePool (Buffer);
+
+  //
+  // Flush the instruction cache so the image data is written before we execute it
+  //
+  InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+
+  DEBUG ((DEBUG_INFO, "Loading driver at 0x%08x EntryPoint=0x%08x\n", (UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.EntryPoint));
+  Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint))(NewImageHandle, gST);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Error: Image at 0x%08x start failed: %r\n", ImageContext.ImageAddress, Status));
+    gBS->FreePages (FfsBuffer, Pages);
+  }
+
+  //
+  // return error to unload >4G copy, if we already relocate itself to <4G.
+  //
+  return EFI_ALREADY_STARTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
new file mode 100644
index 0000000000..fc5a339e8b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
@@ -0,0 +1,478 @@
+/** @file
+  This will be invoked only once. It will call FspMemoryInit API,
+  register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
+  notify to call FspSiliconInit API.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Library/FspWrapperHobProcessLib.h>
+#include <Library/FspWrapperMultiPhaseProcessLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/IoLib.h>
+#include <Ppi/FspSiliconInitDone.h>
+#include <Ppi/EndOfPeiPhase.h>
+#include <Ppi/MemoryDiscovered.h>
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
+#include <Library/FspWrapperApiTestLib.h>
+#include <FspEas.h>
+#include <FspStatusCode.h>
+#include <FspGlobalData.h>
+#include <Library/FspCommonLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <FspmUpd.h>
+
+extern EFI_GUID  gFspHobGuid;
+extern EFI_GUID  gEfiAmdAgesaPkgTokenSpaceGuid;
+extern EFI_GUID  gAmdCpmOemTablePpiGuid;
+
+// The EDK 202208 Doesn't hold these structs.
+typedef enum {
+  EnumMultiPhaseGetVariableRequestInfo  = 0x2,
+  EnumMultiPhaseCompleteVariableRequest = 0x3
+} FSP_MULTI_PHASE_ACTION_23;
+
+typedef enum {
+  FspMultiPhaseMemInitApiIndex = 8
+} FSP_API_INDEX_23;
+
+/**
+  Get the FSP M UPD Data address
+
+  @return FSP-M UPD Data Address
+**/
+volatile
+VOID
+MakePcdNotBeingDeleted (
+  VOID
+  );
+
+UINTN
+GetFspmUpdDataAddress (
+  VOID
+  )
+{
+  if (PcdGet64 (PcdFspmUpdDataAddress64) != 0) {
+    return (UINTN)PcdGet64 (PcdFspmUpdDataAddress64);
+  } else {
+    return (UINTN)PcdGet32 (PcdFspmUpdDataAddress);
+  }
+}
+
+#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
+
+/**
+ 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);
+}
+
+/// AMD CPM OEM TABLE PPI Definition
+
+typedef struct _AMD_CPM_OEM_TABLE_PPI {
+  UINTN     Revision;                         ///< Revision Number
+  UINT16    PlatformId;                       ///< Current Platform Id
+  VOID      *TableList;                       ///< The Point of CPM Definition Table List
+} AMD_CPM_OEM_TABLE_PPI;
+
+// Report FSP-O PEI FV manually.
+EFI_STATUS
+EFIAPI
+GetFspoPeiFv (
+  OUT EFI_FIRMWARE_VOLUME_HEADER  **FspoPeiFvHeader
+  )
+{
+ #ifdef COMPRESS_FSP_REGION
+  BuildMemoryAllocationHob (
+    (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdFspoPeiBaseAddressInMemory),
+    PcdGet32 (PcdFspoPeiRegionSize),
+    EfiACPIMemoryNVS
+    );
+  // Workaround for PSP FV sig check.
+  CopyMem (
+    (VOID *)PcdGet32 (FspoPeiWorkaroundShadowCopyAddress),
+    (VOID *)PcdGet32 (PcdFspoPeiBaseAddressInMemory),
+    PcdGet32 (PcdFspoPeiRegionSize)
+    );
+ #else
+  CopyMem (
+    (VOID *)PcdGet32 (FspoPeiWorkaroundShadowCopyAddress),
+    (VOID *)PcdGet32 (PcdFspoPeiBaseAddressInFlash),
+    PcdGet32 (PcdFspoPeiRegionSize)
+    );
+ #endif
+
+  BuildMemoryAllocationHob (
+    (EFI_PHYSICAL_ADDRESS)PcdGet32 (FspoPeiWorkaroundShadowCopyAddress),
+    PcdGet32 (PcdFspoPeiRegionSize),
+    EfiACPIMemoryNVS
+    );
+  *FspoPeiFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (FspoPeiWorkaroundShadowCopyAddress);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Call FspMemoryInit API.
+
+  @return Status returned by FspMemoryInit API.
+**/
+EFI_STATUS
+PeiFspMemoryInit (
+  VOID
+  )
+{
+  FSP_INFO_HEADER  *FspmHeaderPtr;
+  EFI_STATUS       Status;
+  UINT64           TimeStampCounterStart;
+  VOID             *FspHobListPtr;
+  VOID             *HobData;
+  VOID             *FspmUpdDataPtr;
+  UINTN            *SourceData;
+  UINT32           FspmBaseAddress;
+
+  DEBUG ((DEBUG_INFO, "PeiFspMemoryInit enter\n"));
+
+  FspHobListPtr  = NULL;
+  FspmUpdDataPtr = NULL;
+  // Copied from PlatformInit.
+  ClearSmiAndWake ();
+  ClearAllSmiControlRegisters ();
+  FspmBaseAddress = (UINT32)(UINTN)PcdGet32 (PcdFspmBaseAddressInMemory);
+ #ifndef COMPRESS_FSP_REGION
+  CopyMem ((VOID *)PcdGet32 (PcdFspmBaseAddressInMemory), (VOID *)PcdGet32 (PcdFspmBaseAddressInFlash), (UINT32)PcdGet32 (PcdFspmRegionSize));
+ #endif
+  FspmHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader ((EFI_PHYSICAL_ADDRESS)(UINTN)FspmBaseAddress);
+  DEBUG ((DEBUG_INFO, "Fspm Base Address - 0x%x\n", FspmBaseAddress));
+  DEBUG ((DEBUG_INFO, "FspmHeaderPtr - 0x%x\n", FspmHeaderPtr));
+  if (FspmHeaderPtr == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  BuildMemoryAllocationHob (
+    (EFI_PHYSICAL_ADDRESS)FspmBaseAddress,
+    (UINT32)PcdGet32 (PcdFspmRegionSize),
+    EfiACPIMemoryNVS
+    );
+  FspmHeaderPtr->ImageBase = (UINTN)FspmBaseAddress;
+
+  if ((GetFspmUpdDataAddress () == 0) && (FspmHeaderPtr->CfgRegionSize != 0) && (FspmHeaderPtr->CfgRegionOffset != 0)) {
+    //
+    // Copy default FSP-M UPD data from Flash
+    //
+    FspmUpdDataPtr = AllocateZeroPool ((UINTN)FspmHeaderPtr->CfgRegionSize);
+    ASSERT (FspmUpdDataPtr != NULL);
+    SourceData = (UINTN *)((UINTN)FspmHeaderPtr->ImageBase + (UINTN)FspmHeaderPtr->CfgRegionOffset);
+    CopyMem (FspmUpdDataPtr, SourceData, (UINTN)FspmHeaderPtr->CfgRegionSize);
+  } else {
+    //
+    // External UPD is ready, get the buffer from PCD pointer.
+    //
+    FspmUpdDataPtr = (VOID *)GetFspmUpdDataAddress ();
+    ASSERT (FspmUpdDataPtr != NULL);
+  }
+
+  DEBUG ((DEBUG_INFO, "UpdateFspmUpdData enter\n"));
+  UpdateFspmUpdData (FspmUpdDataPtr);
+  if (((FSPM_UPD_COMMON *)FspmUpdDataPtr)->FspmArchUpd.Revision >= 3) {
+    DEBUG ((DEBUG_INFO, "  StackBase           - 0x%lx\n", ((FSPM_UPD_COMMON_FSP24 *)FspmUpdDataPtr)->FspmArchUpd.StackBase));
+    DEBUG ((DEBUG_INFO, "  StackSize           - 0x%lx\n", ((FSPM_UPD_COMMON_FSP24 *)FspmUpdDataPtr)->FspmArchUpd.StackSize));
+    DEBUG ((DEBUG_INFO, "  BootLoaderTolumSize - 0x%x\n", ((FSPM_UPD_COMMON_FSP24 *)FspmUpdDataPtr)->FspmArchUpd.BootLoaderTolumSize));
+    DEBUG ((DEBUG_INFO, "  BootMode            - 0x%x\n", ((FSPM_UPD_COMMON_FSP24 *)FspmUpdDataPtr)->FspmArchUpd.BootMode));
+  } else {
+    DEBUG ((DEBUG_INFO, "  NvsBufferPtr        - 0x%x\n", ((FSPM_UPD_COMMON *)FspmUpdDataPtr)->FspmArchUpd.NvsBufferPtr));
+    DEBUG ((DEBUG_INFO, "  StackBase           - 0x%x\n", ((FSPM_UPD_COMMON *)FspmUpdDataPtr)->FspmArchUpd.StackBase));
+    DEBUG ((DEBUG_INFO, "  StackSize           - 0x%x\n", ((FSPM_UPD_COMMON *)FspmUpdDataPtr)->FspmArchUpd.StackSize));
+    DEBUG ((DEBUG_INFO, "  BootLoaderTolumSize - 0x%x\n", ((FSPM_UPD_COMMON *)FspmUpdDataPtr)->FspmArchUpd.BootLoaderTolumSize));
+    DEBUG ((DEBUG_INFO, "  BootMode            - 0x%x\n", ((FSPM_UPD_COMMON *)FspmUpdDataPtr)->FspmArchUpd.BootMode));
+  }
+
+  DEBUG ((DEBUG_INFO, "  HobListPtr          - 0x%x\n", &FspHobListPtr));
+
+  // Report FSP-O PEI manually.
+  EFI_FIRMWARE_VOLUME_HEADER  *Header = NULL;
+  if (GetFspoPeiFv (&Header) == EFI_SUCCESS) {
+    ((FSPM_UPD *)FspmUpdDataPtr)->FspmConfig.fsp_o_pei_volume_address = (UINT32)(UINTN)Header;
+    DEBUG ((DEBUG_INFO, "  FSP-O Fv 0x%p\n", Header));
+  }
+
+  TimeStampCounterStart = AsmReadTsc ();
+  Status                = CallFspMemoryInit (FspmUpdDataPtr, &FspHobListPtr);
+
+  //
+  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+  //
+  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+    DEBUG ((DEBUG_INFO, "FspMemoryInitApi requested reset %r\n", Status));
+    CallFspWrapperResetSystem (Status);
+  }
+
+  if ((Status != FSP_STATUS_VARIABLE_REQUEST) && EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ERROR - Failed to execute FspMemoryInitApi(), Status = %r\n", Status));
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  DEBUG ((DEBUG_INFO, "FspMemoryInit status: %r\n", Status));
+  if (Status == FSP_STATUS_VARIABLE_REQUEST) {
+    //
+    // call to Variable request handler
+    //
+    FspWrapperVariableRequestHandler (&FspHobListPtr, FspMultiPhaseMemInitApiIndex);
+  }
+
+  //
+  // See if MultiPhase process is required or not
+  //
+  FspWrapperMultiPhaseHandler (&FspHobListPtr, FspMultiPhaseMemInitApiIndex);    // FspM MultiPhase
+
+  //
+  // Create hobs after memory initialization and not in temp RAM. Hence passing the recorded timestamp here
+  //
+  PERF_START_EX (&gFspApiPerformanceGuid, "EventRec", NULL, TimeStampCounterStart, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+  PERF_END_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+  DEBUG ((DEBUG_INFO, "Total time spent executing FspMemoryInitApi: %d millisecond\n", DivU64x32 (GetTimeInNanoSecond (AsmReadTsc () - TimeStampCounterStart), 1000000)));
+
+  Status = TestFspMemoryInitApiOutput (FspmUpdDataPtr, &FspHobListPtr);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ERROR - TestFspMemoryInitApiOutput () fail, Status = %r\n", Status));
+  }
+
+  DEBUG ((DEBUG_INFO, "  FspHobListPtr (returned) - 0x%x\n", FspHobListPtr));
+  ASSERT (FspHobListPtr != NULL);
+
+  PostFspmHobProcess (FspHobListPtr);
+
+  //
+  // FspHobList is not complete at this moment.
+  // Save FspHobList pointer to hob, so that it can be got later
+  //
+  HobData = BuildGuidHob (
+              &gFspHobGuid,
+              sizeof (VOID *)
+              );
+  ASSERT (HobData != NULL);
+  CopyMem (HobData, &FspHobListPtr, sizeof (FspHobListPtr));
+  return Status;
+}
+
+/**
+  BuildUpdHob
+
+  @return Status returned by FspMemoryInit API.
+**/
+VOID *
+BuildUpdHob (
+  VOID  *FspmBaseAddress
+  )
+{
+  VOID             *FspmUpdDataPtr;
+  FSP_INFO_HEADER  *FspmHeaderPtr;
+  UINTN            *SourceData;
+
+  FspmHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader ((EFI_PHYSICAL_ADDRESS)(UINTN)FspmBaseAddress);
+  DEBUG ((DEBUG_INFO, "Fspm Base Address - 0x%x\n", FspmBaseAddress));
+  DEBUG ((DEBUG_INFO, "FspmHeaderPtr - 0x%x\n", FspmHeaderPtr));
+  ASSERT (FspmHeaderPtr != NULL);
+
+  FspmHeaderPtr->ImageBase = (UINTN)FspmBaseAddress;
+
+  if ((GetFspmUpdDataAddress () == 0) && (FspmHeaderPtr->CfgRegionSize != 0) && (FspmHeaderPtr->CfgRegionOffset != 0)) {
+    //
+    // Copy default FSP-M UPD data from Flash
+    //
+    FspmUpdDataPtr = AllocateZeroPool ((UINTN)FspmHeaderPtr->CfgRegionSize);
+    ASSERT (FspmUpdDataPtr != NULL);
+    SourceData = (UINTN *)((UINTN)FspmHeaderPtr->ImageBase + (UINTN)FspmHeaderPtr->CfgRegionOffset);
+    CopyMem (FspmUpdDataPtr, SourceData, (UINTN)FspmHeaderPtr->CfgRegionSize);
+  } else {
+    //
+    // External UPD is ready, get the buffer from PCD pointer.
+    //
+    FspmUpdDataPtr = (VOID *)GetFspmUpdDataAddress ();
+    ASSERT (FspmUpdDataPtr != NULL);
+  }
+
+  return BuildGuidDataHob (&gAmdFspUpdGuid, &FspmUpdDataPtr, sizeof (VOID *));
+}
+
+/**
+  Do FSP initialization.
+
+  @return FSP initialization status.
+**/
+EFI_STATUS
+EFIAPI
+FspmWrapperInit (
+  VOID
+  )
+{
+  EFI_STATUS                                             Status;
+  EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI  *MeasurementExcludedFvPpi;
+  EFI_PEI_PPI_DESCRIPTOR                                 *MeasurementExcludedPpiList;
+
+  MeasurementExcludedFvPpi = AllocatePool (sizeof (*MeasurementExcludedFvPpi));
+  ASSERT (MeasurementExcludedFvPpi != NULL);
+  MeasurementExcludedFvPpi->Count          = 1;
+  MeasurementExcludedFvPpi->Fv[0].FvBase   = PcdGet32 (PcdFspmBaseAddressInMemory);
+  MeasurementExcludedFvPpi->Fv[0].FvLength = (UINT32)PcdGet32 (PcdFspmRegionSize);
+
+  MeasurementExcludedPpiList = AllocatePool (sizeof (*MeasurementExcludedPpiList));
+  ASSERT (MeasurementExcludedPpiList != NULL);
+  MeasurementExcludedPpiList->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+  MeasurementExcludedPpiList->Guid  = &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid;
+  MeasurementExcludedPpiList->Ppi   = MeasurementExcludedFvPpi;
+
+  Status = EFI_SUCCESS;
+
+  if (PcdGet8 (PcdFspModeSelection) == 1) {
+    Status = PeiFspMemoryInit ();
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    Status = PeiServicesInstallPpi (MeasurementExcludedPpiList);
+    ASSERT_EFI_ERROR (Status);
+    VOID  *FspmBaseAddress = (VOID *)(UINTN)PcdGet32 (PcdFspmBaseAddressInMemory);
+ #ifndef COMPRESS_FSP_REGION
+    CopyMem (FspmBaseAddress, (VOID *)PcdGet32 (PcdFspmBaseAddressInFlash), (UINT32)PcdGet32 (PcdFspmRegionSize));
+ #endif
+    // Build a Upd address pointer guid hob for FSP.
+    VOID  **upd_guid_hob = BuildUpdHob (FspmBaseAddress);
+    DEBUG ((DEBUG_INFO, "upd_guid_hob: 0x%x\n", *upd_guid_hob));
+    ASSERT (upd_guid_hob != NULL);
+    // Update UPD variables according to OEM requirement
+    // Sample code
+    //  FSPM_UPD * volatile fsp_m_upd = *upd_guid_hob;
+    //  FSP_M_CONFIG * volatile fsp_m_cfg = &fsp_m_upd->FspmConfig;
+    //  fsp_m_cfg->DbgFchUsbUsb0DrdMode = xx;
+
+    BuildMemoryAllocationHob (
+      (UINTN)FspmBaseAddress,
+      PcdGet32 (PcdFspmRegionSize),
+      EfiACPIMemoryNVS
+      );
+    PeiServicesInstallFvInfoPpi (
+      NULL,
+      (VOID *)(UINTN)FspmBaseAddress,
+      PcdGet32 (PcdFspmRegionSize),
+      NULL,
+      NULL
+      );
+    BuildFvHob (
+      (EFI_PHYSICAL_ADDRESS)(UINTN)FspmBaseAddress,
+      PcdGet32 (PcdFspmRegionSize)
+      );
+
+    EFI_FIRMWARE_VOLUME_HEADER  *FspoBaseAddress = NULL;
+    Status = GetFspoPeiFv (&FspoBaseAddress);
+    PeiServicesInstallFvInfoPpi (
+      NULL,
+      FspoBaseAddress,
+      PcdGet32 (PcdFspoPeiRegionSize),
+      NULL,
+      NULL
+      );
+    BuildFvHob (
+      (EFI_PHYSICAL_ADDRESS)(UINTN)FspoBaseAddress,
+      PcdGet32 (PcdFspoPeiRegionSize)
+      );
+  }
+
+  return Status;
+}
+
+/**
+  This is the entrypoint of PEIM
+
+  @param[in] FileHandle  Handle of the file being invoked.
+  @param[in] PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS if it completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+FspmWrapperPeimEntryPoint (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  DEBUG ((DEBUG_INFO, "FspmWrapperPeimEntryPoint\n"));
+
+  FspmWrapperInit ();
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
new file mode 100644
index 0000000000..b17762391e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
@@ -0,0 +1,92 @@
+## @file
+# FSP-M wrapper PEI Module
+#
+# This PEIM initialize FSP.
+# This will be invoked only once. It will call FspMemoryInit API,
+# register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
+# notify to call FspSiliconInit API.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = FspmWrapperPeim
+  FILE_GUID                      = 9FAAD0FF-0E0C-4885-A738-BAB4E4FA1E66
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = PEIM
+  ENTRY_POINT                    = FspmWrapperPeimEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[LibraryClasses]
+  PeimEntryPoint
+  PeiServicesLib
+  PeiServicesTablePointerLib
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  DebugLib
+  HobLib
+  FspWrapperPlatformLib
+  FspWrapperHobProcessLib
+  CpuLib
+  UefiCpuLib
+  PeCoffGetEntryPointLib
+  PeCoffExtraActionLib
+  PerformanceLib
+  TimerLib
+  FspWrapperApiLib
+  FspWrapperApiTestLib
+  IoLib
+#-  FspMeasurementLib
+  FspWrapperMultiPhaseProcessLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  SecurityPkg/SecurityPkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[Pcd]
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress    ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection      ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFsptBaseAddress       ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig  ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress64  ## CONSUMES
+  gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInFlash
+  gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInMemory
+  gFsp2WrapperTokenSpaceGuid.PcdFspoPeiBaseAddressInFlash
+  gFsp2WrapperTokenSpaceGuid.PcdFspoPeiBaseAddressInMemory
+  gFsp2WrapperTokenSpaceGuid.PcdFspmRegionSize
+  gFsp2WrapperTokenSpaceGuid.PcdFspoPeiRegionSize
+  gFsp2WrapperTokenSpaceGuid.FspoPeiWorkaroundShadowCopyAddress
+
+[Sources]
+  FspmWrapperPeim.c
+
+[Guids]
+  gFspHobGuid                           ## PRODUCES ## HOB
+  gFspApiPerformanceGuid                ## SOMETIMES_CONSUMES ## GUID
+  gPlatformPkgTokenSpaceGuid
+  gAmdFspUpdGuid
+
+[Ppis]
+#-  gEdkiiTcgPpiGuid                                       ## NOTIFY
+  gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid    ## PRODUCES
+
+
+[Depex]
+  gEfiPeiMasterBootModePpiGuid
+  AND gEfiPeiReadOnlyVariable2PpiGuid
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.c
new file mode 100644
index 0000000000..bb5e12cba9
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.c
@@ -0,0 +1,206 @@
+/** @file
+  This driver will register two callbacks to call fsp's notifies.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Library/HobLib.h>
+#include <FspStatusCode.h>
+#include "../Include/FspGlobalData.h"
+
+extern EFI_GUID  gFspHobGuid;
+extern EFI_GUID  gEfiResetArchProtocolGuid;
+extern EFI_GUID  gAmdFspSetupTableInitDoneGuid;
+
+EFI_EVENT  gAmdFspSetupTableInitDoneEvent;
+EFI_EVENT  gResetDoneEvent;
+
+/**
+  Relocate this image under 4G memory.
+
+  @param  ImageHandle  Handle of driver image.
+  @param  SystemTable  Pointer to system table.
+
+  @retval EFI_SUCCESS  Image successfully relocated.
+  @retval EFI_ABORTED  Failed to relocate image.
+
+**/
+EFI_STATUS
+RelocateImageUnder4GIfNeeded (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+EFI_STATUS
+EFIAPI
+FspWrapperMultiPhaseHandler (
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex
+  );
+
+STATIC
+VOID *
+GetFspHobList (
+  VOID
+  )
+{
+  EFI_HOB_GUID_TYPE  *GuidHob;
+
+  GuidHob = GetFirstGuidHob (&gFspHobGuid);
+  if (GuidHob != NULL) {
+    return *(VOID **)GET_GUID_HOB_DATA (GuidHob);
+  } else {
+    return NULL;
+  }
+}
+
+/**
+  Callback function after runtime reset being ready immediately.
+
+  @param[in] Event      Not used.
+  @param[in] Context    Not used.
+
+**/
+VOID
+EFIAPI
+DoResetAfterRtImmediately (
+  IN  EFI_EVENT  Event,
+  IN  VOID       *Context
+  )
+{
+  gBS->CloseEvent (Event);
+  gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+}
+
+/**
+  Callback function after FSP finished applying setup table in DXE phase.
+
+  The platform is considered to stop ANY critical services, and then do COLD RESET.
+
+  @param[in] Event      Not used.
+  @param[in] Context    Not used.
+
+**/
+VOID
+EFIAPI
+CheckAndRebootSystemAfterFspSetupTable (
+  IN  EFI_EVENT  Event,
+  IN  VOID       *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  gBS->CloseEvent (Event);
+  VOID  *Registration;
+
+  DEBUG ((DEBUG_INFO, "FSP Setup table Done!\n"));
+  DEBUG ((DEBUG_INFO, "Reset?%s\n", PcdGetBool (PcdAmdFspSetupTableInitNeedsReset) ? L"TRUE" : L"FALSE"));
+  if (!PcdGetBool (PcdAmdFspSetupTableInitNeedsReset)) {
+    return;
+  }
+
+  // DO RESET HERE!
+  Status = gBS->LocateProtocol (&gEfiResetArchProtocolGuid, NULL, (VOID **)&Registration);
+  if ( !EFI_ERROR (Status)) {
+    gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+    // Will not return here.
+  }
+
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  DoResetAfterRtImmediately,
+                  NULL,
+                  &gResetDoneEvent
+                  );
+  if (!EFI_ERROR (Status)) {
+    Registration = NULL;
+    Status       = gBS->RegisterProtocolNotify (
+                          &gEfiResetArchProtocolGuid,
+                          gResetDoneEvent,
+                          &Registration
+                          );
+  }
+}
+
+/**
+  Main entry for the FSP DXE module.
+
+  This routine registers two callbacks to call fsp's notifies.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+FspsMultiPhaseSiInitDxeEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  VOID        *Registration;
+
+  if (!PcdGet8 (PcdFspModeSelection)) {
+    // Dispatch Mode
+    DEBUG ((DEBUG_INFO, "Waiting for FSP Setup table...\n"));
+    Status = gBS->CreateEvent (
+                    EVT_NOTIFY_SIGNAL,
+                    TPL_CALLBACK,
+                    CheckAndRebootSystemAfterFspSetupTable,
+                    NULL,
+                    &gAmdFspSetupTableInitDoneEvent
+                    );
+    if (!EFI_ERROR (Status)) {
+      Registration = NULL;
+      Status       = gBS->RegisterProtocolNotify (
+                            &gAmdFspSetupTableInitDoneGuid,
+                            gAmdFspSetupTableInitDoneEvent,
+                            &Registration
+                            );
+    }
+
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Load this driver's image to memory
+  //
+  Status = RelocateImageUnder4GIfNeeded (ImageHandle, SystemTable);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Cannot relocate into 4G- Mem!\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  VOID  *FspHobList = (VOID *)((UINTN)GetFspHobList ()&0xFFFFFFFF);
+
+  return FspWrapperMultiPhaseHandler (&FspHobList, FspMultiPhaseSiInitApiIndex);
+}
+
+VOID
+EFIAPI
+CallFspWrapperResetSystem (
+  IN EFI_STATUS  FspStatusResetType
+  )
+{
+  //
+  // Perform reset according to the type.
+  //
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
new file mode 100644
index 0000000000..1ff3ef8964
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
@@ -0,0 +1,74 @@
+## @file
+# FSP DXE Module
+#
+# This driver will register two callbacks to call fsp's notifies.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FspsMultiPhaseSiInitDxe
+  FILE_GUID                      = B37267AD-4F52-41E2-BBD0-6BAEFD911A25
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = FspsMultiPhaseSiInitDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  FspsMultiPhaseSiInitDxe.c
+  LoadBelow4G.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  DebugLib
+  BaseMemoryLib
+  UefiLib
+  FspWrapperApiLib
+  PeCoffLib
+  CacheMaintenanceLib
+  DxeServicesLib
+  PerformanceLib
+  HobLib
+  FspWrapperMultiPhaseProcessLib
+
+[Protocols]
+  gEfiSmbusHcProtocolGuid                           ## PRODUCES  FROM_FSP
+  gEfiSmmAccess2ProtocolGuid                        ## PRODUCES  FROM_FSP
+  gEfiSmmControl2ProtocolGuid                       ## PRODUCES  FROM_FSP
+  gEfiResetArchProtocolGuid                         ## PRODUCES  FROM_FSP
+  gFchInitDonePolicyProtocolGuid                    ## PRODUCES  FROM_FSP
+  gEfiSmmBase2ProtocolGuid                          ## CONSUMES  FOR_FSP
+  gEfiSmmCommunicationProtocolGuid                  ## CONSUMES  FOR_FSP
+  gEfiMmCommunication2ProtocolGuid                  ## CONSUMES  FOR_FSP
+  gAmdFspSetupTableInitDoneGuid                     ## CONSUMES  FOR_FSP
+ #gEfiSmmReadyToLockProtocolGuid                    ## CONSUMES  FOR_FSP
+
+[Guids]
+  gFspApiPerformanceGuid                            ## SOMETIMES_CONSUMES ## GUID
+  gEfiEventExitBootServicesGuid                     ## CONSUMES ## Event
+  gFspHobGuid                                       ## CONSUMES ## HOB
+
+[Pcd]
+  gIntelFsp2WrapperTokenSpaceGuid.PcdSkipFspApi       ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdFspSetupTableInitNeedsReset
+
+[Depex]
+  TRUE
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/LoadBelow4G.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/LoadBelow4G.c
new file mode 100644
index 0000000000..ae05556cc9
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/LoadBelow4G.c
@@ -0,0 +1,148 @@
+/** @file
+Implements LoadBelow4G.C
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/UefiLib.h>
+
+/**
+  Relocate this image under 4G memory.
+
+  @param  ImageHandle  Handle of driver image.
+  @param  SystemTable  Pointer to system table.
+
+  @retval EFI_SUCCESS  Image successfully relocated.
+  @retval EFI_ABORTED  Failed to relocate image.
+
+**/
+EFI_STATUS
+RelocateImageUnder4GIfNeeded (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                    Status;
+  UINT8                         *Buffer;
+  UINTN                         BufferSize;
+  EFI_HANDLE                    NewImageHandle;
+  UINTN                         Pages;
+  EFI_PHYSICAL_ADDRESS          FfsBuffer;
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+  VOID                          *Interface;
+
+  //
+  // If it is already <4G, no need do relocate
+  //
+  if ((UINTN)RelocateImageUnder4GIfNeeded < 0xFFFFFFFF) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // If locate gEfiCallerIdGuid success, it means 2nd entry.
+  //
+  Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &Interface);
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "FspNotifyDxe - 2nd entry\n"));
+    return EFI_SUCCESS;
+  }
+
+  DEBUG ((DEBUG_INFO, "FspNotifyDxe - 1st entry\n"));
+
+  //
+  // Here we install a dummy handle
+  //
+  NewImageHandle = NULL;
+  Status         = gBS->InstallProtocolInterface (
+                          &NewImageHandle,
+                          &gEfiCallerIdGuid,
+                          EFI_NATIVE_INTERFACE,
+                          NULL
+                          );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Reload image itself to <4G mem
+  //
+  Status = GetSectionFromAnyFv (
+             &gEfiCallerIdGuid,
+             EFI_SECTION_PE32,
+             0,
+             (VOID **)&Buffer,
+             &BufferSize
+             );
+  ASSERT_EFI_ERROR (Status);
+  ImageContext.Handle    = Buffer;
+  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+  //
+  // Get information about the image being loaded
+  //
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
+  if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
+    Pages = EFI_SIZE_TO_PAGES ((UINTN)(ImageContext.ImageSize + ImageContext.SectionAlignment));
+  } else {
+    Pages = EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize);
+  }
+
+  FfsBuffer = 0xFFFFFFFF;
+  Status    = gBS->AllocatePages (
+                     AllocateMaxAddress,
+                     EfiBootServicesCode,
+                     Pages,
+                     &FfsBuffer
+                     );
+  ASSERT_EFI_ERROR (Status);
+  ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)FfsBuffer;
+  //
+  // Align buffer on section boundary
+  //
+  ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
+  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);
+  //
+  // Load the image to our new buffer
+  //
+  Status = PeCoffLoaderLoadImage (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Relocate the image in our new buffer
+  //
+  Status = PeCoffLoaderRelocateImage (&ImageContext);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
+  //
+  gBS->FreePool (Buffer);
+
+  //
+  // Flush the instruction cache so the image data is written before we execute it
+  //
+  InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+
+  DEBUG ((DEBUG_INFO, "Loading driver at 0x%08x EntryPoint=0x%08x\n", (UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.EntryPoint));
+  Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint))(NewImageHandle, gST);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Error: Image at 0x%08x start failed: %r\n", ImageContext.ImageAddress, Status));
+    gBS->FreePages (FfsBuffer, Pages);
+  }
+
+  //
+  // return error to unload >4G copy, if we already relocate itself to <4G.
+  //
+  return EFI_ALREADY_STARTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
new file mode 100644
index 0000000000..e6a589bcb5
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
@@ -0,0 +1,632 @@
+/** @file
+  This will be invoked only once. It will call FspMemoryInit API,
+  register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
+  notify to call FspSiliconInit API.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Library/FspWrapperHobProcessLib.h>
+#include "../Include/Library/FspWrapperMultiPhaseProcessLib.h"
+#include "../Include/Library/FspWrapperPlatformMultiPhaseLib.h"
+#include <Library/TimerLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Ppi/FspSiliconInitDone.h>
+#include <Ppi/EndOfPeiPhase.h>
+#include <Ppi/MemoryDiscovered.h>
+#include <Ppi/TemporaryRamDone.h>
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
+#include <Library/FspWrapperApiTestLib.h>
+#include <FspEas.h>
+#include <FspStatusCode.h>
+#include <FspGlobalData.h>
+#include <Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h>
+#include <FspExportedInterfaceHob.h>
+
+extern EFI_PEI_NOTIFY_DESCRIPTOR  mS3EndOfPeiNotifyDesc;
+extern EFI_GUID                   gFspHobGuid;
+
+STATIC CONST EFI_GUID  SmmDriverVolumeFileName =
+{
+  0x82DFABE7, 0xCD0E, 0x44D3, { 0xAF, 0xBE, 0x46, 0x82, 0x21, 0xD1, 0x08, 0xC4 }
+};
+
+/**
+  This function handles S3 resume task at the end of PEI.
+
+  @param[in] PeiServices    Pointer to PEI Services Table.
+  @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that
+                            caused this function to execute.
+  @param[in] Ppi            Pointer to the PPI data associated with this function.
+
+  @retval EFI_STATUS        Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+S3EndOfPeiNotify (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
+  IN VOID                       *Ppi
+  );
+
+EFI_PEI_NOTIFY_DESCRIPTOR  mS3EndOfPeiNotifyDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiEndOfPeiSignalPpiGuid,
+  S3EndOfPeiNotify
+};
+
+/**
+  This function handles S3 resume task at the end of PEI.
+
+  @param[in] PeiServices    Pointer to PEI Services Table.
+  @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that
+                            caused this function to execute.
+  @param[in] Ppi            Pointer to the PPI data associated with this function.
+
+  @retval EFI_STATUS        Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+S3EndOfPeiNotify (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
+  IN VOID                       *Ppi
+  )
+{
+  NOTIFY_PHASE_PARAMS  NotifyPhaseParams;
+  EFI_STATUS           Status;
+
+  DEBUG ((DEBUG_INFO, "S3EndOfPeiNotify enter\n"));
+
+  NotifyPhaseParams.Phase = EnumInitPhaseAfterPciEnumeration;
+  Status                  = CallFspNotifyPhase (&NotifyPhaseParams);
+  DEBUG ((DEBUG_INFO, "FSP S3NotifyPhase AfterPciEnumeration status: 0x%x\n", Status));
+
+  //
+  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+  //
+  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+    DEBUG ((DEBUG_INFO, "FSP S3NotifyPhase AfterPciEnumeration requested reset 0x%x\n", Status));
+    CallFspWrapperResetSystem (Status);
+  }
+
+  NotifyPhaseParams.Phase = EnumInitPhaseReadyToBoot;
+  Status                  = CallFspNotifyPhase (&NotifyPhaseParams);
+  DEBUG ((DEBUG_INFO, "FSP S3NotifyPhase ReadyToBoot status: 0x%x\n", Status));
+
+  //
+  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+  //
+  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+    DEBUG ((DEBUG_INFO, "FSP S3NotifyPhase ReadyToBoot requested reset 0x%x\n", Status));
+    CallFspWrapperResetSystem (Status);
+  }
+
+  NotifyPhaseParams.Phase = EnumInitPhaseEndOfFirmware;
+  Status                  = CallFspNotifyPhase (&NotifyPhaseParams);
+  DEBUG ((DEBUG_INFO, "FSP S3NotifyPhase EndOfFirmware status: 0x%x\n", Status));
+
+  //
+  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+  //
+  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+    DEBUG ((DEBUG_INFO, "FSP S3NotifyPhase EndOfFirmware requested reset 0x%x\n", Status));
+    CallFspWrapperResetSystem (Status);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return Hob list produced by FSP.
+
+  @param[in]  PeiServices  The pointer to the PEI Services Table.
+  @param[in]  This         The pointer to this instance of this PPI.
+  @param[out] FspHobList   The pointer to Hob list produced by FSP.
+
+  @return EFI_SUCCESS      Return Hob list produced by FSP successfully.
+**/
+EFI_STATUS
+EFIAPI
+FspSiliconInitDoneGetFspHobList (
+  IN  CONST EFI_PEI_SERVICES     **PeiServices,
+  IN  FSP_SILICON_INIT_DONE_PPI  *This,
+  OUT VOID                       **FspHobList
+  );
+
+FSP_SILICON_INIT_DONE_PPI  mFspSiliconInitDonePpi = {
+  FspSiliconInitDoneGetFspHobList
+};
+
+EFI_PEI_PPI_DESCRIPTOR  mPeiFspSiliconInitDonePpi = {
+  EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+  &gFspSiliconInitDonePpiGuid,
+  &mFspSiliconInitDonePpi
+};
+
+/**
+  Return Hob list produced by FSP.
+
+  @param[in]  PeiServices  The pointer to the PEI Services Table.
+  @param[in]  This         The pointer to this instance of this PPI.
+  @param[out] FspHobList   The pointer to Hob list produced by FSP.
+
+  @return EFI_SUCCESS      Return Hob list produced by FSP successfully.
+**/
+EFI_STATUS
+EFIAPI
+FspSiliconInitDoneGetFspHobList (
+  IN  CONST EFI_PEI_SERVICES     **PeiServices,
+  IN  FSP_SILICON_INIT_DONE_PPI  *This,
+  OUT VOID                       **FspHobList
+  )
+{
+  EFI_HOB_GUID_TYPE  *GuidHob;
+
+  GuidHob = GetFirstGuidHob (&gFspHobGuid);
+  if (GuidHob != NULL) {
+    *FspHobList = *(VOID **)GET_GUID_HOB_DATA (GuidHob);
+    return EFI_SUCCESS;
+  } else {
+    return EFI_NOT_FOUND;
+  }
+}
+
+/**
+  Get the FSP S UPD Data address
+
+  @return FSP-S UPD Data Address
+**/
+UINTN
+GetFspsUpdDataAddress (
+  VOID
+  )
+{
+  if (PcdGet64 (PcdFspsUpdDataAddress64) != 0) {
+    return (UINTN)PcdGet64 (PcdFspsUpdDataAddress64);
+  } else {
+    return (UINTN)PcdGet32 (PcdFspsUpdDataAddress);
+  }
+}
+
+/**
+  This function is for FSP dispatch mode to perform post FSP-S process.
+
+  @param[in] PeiServices    Pointer to PEI Services Table.
+  @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that
+                            caused this function to execute.
+  @param[in] Ppi            Pointer to the PPI data associated with this function.
+
+  @retval EFI_STATUS        Status returned by PeiServicesInstallPpi ()
+**/
+EFI_STATUS
+EFIAPI
+FspsWrapperEndOfPeiNotify (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
+  IN VOID                       *Ppi
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // This step may include platform specific process in some boot loaders so
+  // aligning the same behavior between API and Dispatch modes.
+  // Note: In Dispatch mode no FspHobList so passing NULL to function and
+  //       expecting function will handle it.
+  //
+  PostFspsHobProcess (NULL);
+
+  //
+  // Install FspSiliconInitDonePpi so that any other driver can consume this info.
+  //
+  Status = PeiServicesInstallPpi (&mPeiFspSiliconInitDonePpi);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+EFI_PEI_NOTIFY_DESCRIPTOR  mFspsWrapperEndOfPeiNotifyDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiEndOfPeiSignalPpiGuid,
+  FspsWrapperEndOfPeiNotify
+};
+
+/**
+  This function is called after PEI core discover memory and finish migration.
+
+  @param[in] PeiServices    Pointer to PEI Services Table.
+  @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that
+                            caused this function to execute.
+  @param[in] Ppi            Pointer to the PPI data associated with this function.
+
+  @retval EFI_STATUS        Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+PeiMemoryDiscoveredNotify (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
+  IN VOID                       *Ppi
+  );
+
+EFI_PEI_NOTIFY_DESCRIPTOR  mPeiMemoryDiscoveredNotifyDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiPeiMemoryDiscoveredPpiGuid,
+  PeiMemoryDiscoveredNotify
+};
+
+extern
+RETURN_STATUS
+EFIAPI
+LzmaGuidedSectionGetInfo (
+  IN  CONST VOID  *InputSection,
+  OUT UINT32      *OutputBufferSize,
+  OUT UINT32      *ScratchBufferSize,
+  OUT UINT16      *SectionAttribute
+  )
+;
+
+extern
+RETURN_STATUS
+EFIAPI
+LzmaGuidedSectionExtraction (
+  IN CONST  VOID    *InputSection,
+  OUT       VOID    **OutputBuffer,
+  OUT       VOID    *ScratchBuffer         OPTIONAL,
+  OUT       UINT32  *AuthenticationStatus
+  )
+;
+
+/**
+  This function is called after PEI core discover memory and finish migration.
+
+  @param[in] PeiServices    Pointer to PEI Services Table.
+  @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that
+                            caused this function to execute.
+  @param[in] Ppi            Pointer to the PPI data associated with this function.
+
+  @retval EFI_STATUS        Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+PeiMemoryDiscoveredNotify (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
+  IN VOID                       *Ppi
+  )
+{
+  FSP_INFO_HEADER      *FspsHeaderPtr;
+  UINT64               TimeStampCounterStart;
+  EFI_STATUS           Status;
+  VOID                 *FspHobListPtr;
+  EFI_HOB_GUID_TYPE    *GuidHob;
+  FSPS_UPD_COMMON      *FspsUpdDataPtr;
+  UINTN                *SourceData;
+  EFI_PEI_FV_HANDLE    VolumeHandle;
+  EFI_PEI_FILE_HANDLE  FileHandle;
+  EFI_FV_FILE_INFO     FileInfo;
+  UINT32               FvIndex = 0;
+  UINT32               DecompressedSmmFvSize, TemporaryBufferSize;
+  VOID                 *DecompressedFv, *TemporaryBuffer;
+  EFI_BOOT_MODE        BootMode;
+
+  //
+  // Get boot mode
+  //
+  Status = PeiServicesGetBootMode (&BootMode);
+  ASSERT_EFI_ERROR (Status);
+  DEBUG ((DEBUG_INFO, "PeiMemoryDiscoveredNotify enter\n"));
+  FspsUpdDataPtr = NULL;
+
+  VOID  *FspsBaseAddressInMem = (VOID *)(UINTN)PcdGet32 (PcdFspsBaseAddressInMemory);
+
+  FspsHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader ((EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdFspsBaseAddressInMemory));
+  BuildMemoryAllocationHob (
+    (EFI_PHYSICAL_ADDRESS)(UINTN)FspsBaseAddressInMem,
+    (UINT64)PcdGet32 (PcdFspsRegionSize),
+    EfiACPIMemoryNVS
+    );
+  FspsHeaderPtr->ImageBase = (UINTN)FspsBaseAddressInMem;
+
+  if (BootMode != BOOT_ON_S3_RESUME) {
+    // Get SMM Driver Volume from flash, and extract/deflate it.
+    while (PeiServicesFfsFindNextVolume (FvIndex, &VolumeHandle) != EFI_NOT_FOUND) {
+      if (PeiServicesFfsFindFileByName (&SmmDriverVolumeFileName, VolumeHandle, &FileHandle) == EFI_SUCCESS) {
+        break;
+      }
+
+      FvIndex++;
+    }
+
+    ASSERT (FileHandle != NULL);
+    PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
+    DEBUG ((DEBUG_INFO, "SMM Driver File:%p,0x%x bytes.\n", FileInfo.Buffer, FileInfo.BufferSize));
+    UINT16  Attribute;
+    Status = LzmaGuidedSectionGetInfo (
+               FileInfo.Buffer,
+               &DecompressedSmmFvSize,
+               &TemporaryBufferSize,
+               &Attribute
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Cannot Get LZMA Section info!\n"));
+      ASSERT (FALSE);
+      return EFI_UNSUPPORTED;
+    }
+
+    DEBUG ((DEBUG_INFO, "FV Decompress size:%d\n", DecompressedSmmFvSize));
+    EFI_PHYSICAL_ADDRESS  PhysicalAddress;
+    Status =  PeiServicesAllocatePages (
+                EfiBootServicesData,
+                EFI_SIZE_TO_PAGES (DecompressedSmmFvSize),
+                &PhysicalAddress
+                );
+    DecompressedFv = (VOID *)(UINTN)PhysicalAddress;
+    Status        |= PeiServicesAllocatePages (
+                       EfiBootServicesData,
+                       EFI_SIZE_TO_PAGES (TemporaryBufferSize),
+                       &PhysicalAddress
+                       );
+    TemporaryBuffer = (VOID *)(UINTN)PhysicalAddress;
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Cannot allocate memory!%r\n", Status));
+      return EFI_UNSUPPORTED;
+    }
+
+    UINT32  AuthenticationStatus;
+    Status = LzmaGuidedSectionExtraction (FileInfo.Buffer, &DecompressedFv, TemporaryBuffer, &AuthenticationStatus);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Cannot Decompress LZMA Section!:%r\n", Status));
+      ASSERT (FALSE);
+      return EFI_UNSUPPORTED;
+    }
+
+    PeiServicesFreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (TemporaryBufferSize));
+
+    FSP_EXPORTED_INTERFACE_HOB  *ExportedInterfaceHob;
+    GuidHob = GetFirstGuidHob (&gFspHobGuid);
+    if (GuidHob != NULL) {
+      GuidHob              = *(VOID **)GET_GUID_HOB_DATA (GuidHob);
+      GuidHob              = GetNextGuidHob (&gFspExportedInterfaceHobGuid, GuidHob);
+      ExportedInterfaceHob = GET_GUID_HOB_DATA (GuidHob);
+      DEBUG ((DEBUG_INFO, "FSP Exported interface HOB:%p\n", ExportedInterfaceHob));
+      DEBUG ((DEBUG_INFO, "FSP DecompressedFv:%p\n", (UINT8 *)DecompressedFv+0x10)); // Skip RAW section.
+      ExportedInterfaceHob->SmmDriverVolume     = (UINT8 *)DecompressedFv+0x10;      // Skip RAW section.
+      ExportedInterfaceHob->SmmDriverVolumeSize = DecompressedSmmFvSize;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "FspsHeaderPtr - 0x%x\n", FspsHeaderPtr));
+  if (FspsHeaderPtr == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if ((GetFspsUpdDataAddress () == 0) && (FspsHeaderPtr->CfgRegionSize != 0) && (FspsHeaderPtr->CfgRegionOffset != 0)) {
+    //
+    // Copy default FSP-S UPD data from Flash
+    //
+    FspsUpdDataPtr = (FSPS_UPD_COMMON *)AllocateZeroPool ((UINTN)FspsHeaderPtr->CfgRegionSize);
+    ASSERT (FspsUpdDataPtr != NULL);
+    SourceData = (UINTN *)((UINTN)FspsHeaderPtr->ImageBase + (UINTN)FspsHeaderPtr->CfgRegionOffset);
+    CopyMem (FspsUpdDataPtr, SourceData, (UINTN)FspsHeaderPtr->CfgRegionSize);
+  } else {
+    FspsUpdDataPtr = (FSPS_UPD_COMMON *)GetFspsUpdDataAddress ();
+    ASSERT (FspsUpdDataPtr != NULL);
+  }
+
+  UpdateFspsUpdData ((VOID *)FspsUpdDataPtr);
+
+  TimeStampCounterStart = AsmReadTsc ();
+  PERF_START_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+  Status = CallFspSiliconInit ((VOID *)FspsUpdDataPtr);
+
+  //
+  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+  //
+  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+    DEBUG ((DEBUG_INFO, "FspSiliconInitApi requested reset %r\n", Status));
+    CallFspWrapperResetSystem (Status);
+  }
+
+  if ((Status != FSP_STATUS_VARIABLE_REQUEST) && EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ERROR - Failed to execute FspSiliconInitApi(), Status = %r\n", Status));
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  DEBUG ((DEBUG_INFO, "FspSiliconInit status: %r\n", Status));
+
+  if (Status == FSP_STATUS_VARIABLE_REQUEST) {
+    //
+    // call to Variable request handler
+    //
+    FspWrapperVariableRequestHandler (&FspHobListPtr, FspMultiPhaseSiInitApiIndex);
+  }
+
+  //
+  // See if MultiPhase process is required or not
+  //
+  FspWrapperMultiPhaseHandler (&FspHobListPtr, FspMultiPhaseSiInitApiIndex);    // FspS MultiPhase
+
+  PERF_END_EX (&gFspApiPerformanceGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+  DEBUG ((DEBUG_INFO, "Total time spent executing FspSiliconInitApi: %d millisecond\n", DivU64x32 (GetTimeInNanoSecond (AsmReadTsc () - TimeStampCounterStart), 1000000)));
+
+  Status = TestFspSiliconInitApiOutput ((VOID *)NULL);
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ERROR - TestFspSiliconInitApiOutput () fail, Status = %r\n", Status));
+  }
+
+  //
+  // Now FspHobList complete, process it
+  //
+  GuidHob = GetFirstGuidHob (&gFspHobGuid);
+  ASSERT (GuidHob != NULL);
+  FspHobListPtr = *(VOID **)GET_GUID_HOB_DATA (GuidHob);
+  DEBUG ((DEBUG_INFO, "FspHobListPtr - 0x%x\n", FspHobListPtr));
+  PostFspsHobProcess (FspHobListPtr);
+
+  //
+  // Install FspSiliconInitDonePpi so that any other driver can consume this info.
+  //
+  Status = PeiServicesInstallPpi (&mPeiFspSiliconInitDonePpi);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Do FSP initialization in API mode.
+
+  @retval EFI_STATUS        Always return EFI_SUCCESS
+**/
+EFI_STATUS
+FspsWrapperInitApiMode (
+  VOID
+  )
+{
+  EFI_STATUS     Status;
+  EFI_BOOT_MODE  BootMode;
+
+  //
+  // Register MemoryDiscovered Notify to run FspSiliconInit
+  //
+  Status = PeiServicesNotifyPpi (&mPeiMemoryDiscoveredNotifyDesc);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register EndOfPei Notify for S3 to run FSP NotifyPhase
+  //
+  PeiServicesGetBootMode (&BootMode);
+  if (BootMode == BOOT_ON_S3_RESUME) {
+    Status = PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Do FSP initialization in Dispatch mode.
+
+  @retval FSP initialization status.
+**/
+EFI_STATUS
+FspsWrapperInitDispatchMode (
+  VOID
+  )
+{
+  EFI_STATUS                                             Status;
+  EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI  *MeasurementExcludedFvPpi;
+  EFI_PEI_PPI_DESCRIPTOR                                 *MeasurementExcludedPpiList;
+  EFI_BOOT_MODE                                          BootMode;
+
+  PeiServicesGetBootMode (&BootMode);
+  Status = EFI_SUCCESS;
+
+  if (BootMode != BOOT_ON_S3_RESUME) {
+    MeasurementExcludedFvPpi = AllocatePool (sizeof (*MeasurementExcludedFvPpi));
+    ASSERT (MeasurementExcludedFvPpi != NULL);
+    MeasurementExcludedFvPpi->Count          = 1;
+    MeasurementExcludedFvPpi->Fv[0].FvBase   = PcdGet32 (PcdFspsBaseAddressInMemory);
+    MeasurementExcludedFvPpi->Fv[0].FvLength = PcdGet32 (PcdFspsRegionSize);
+
+    MeasurementExcludedPpiList = AllocatePool (sizeof (*MeasurementExcludedPpiList));
+    ASSERT (MeasurementExcludedPpiList != NULL);
+    MeasurementExcludedPpiList->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+    MeasurementExcludedPpiList->Guid  = &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid;
+    MeasurementExcludedPpiList->Ppi   = MeasurementExcludedFvPpi;
+
+    Status = PeiServicesInstallPpi (MeasurementExcludedPpiList);
+    ASSERT_EFI_ERROR (Status);
+
+    EFI_FIRMWARE_VOLUME_HEADER  *FspsBaseAddressInMem = (VOID *)(UINTN)PcdGet32 (PcdFspsBaseAddressInMemory);
+    //
+    // FSP-S Wrapper running in Dispatch mode and reports FSP-S FV to PEI dispatcher.
+    //
+    PeiServicesInstallFvInfoPpi (
+      NULL,
+      (VOID *)(UINTN)FspsBaseAddressInMem,
+      (UINT32)PcdGet32 (PcdFspsRegionSize),
+      NULL,
+      NULL
+      );
+
+    VOID  *FspoDxeBaseAddressInMem = (VOID *)(UINTN)PcdGet32 (PcdFspoDxeBaseAddressInMemory);
+    PeiServicesInstallFvInfoPpi (
+      NULL,
+      FspoDxeBaseAddressInMem,
+      (UINT32)PcdGet32 (PcdFspoDxeRegionSize),
+      NULL,
+      NULL
+      );
+    BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)FspsBaseAddressInMem, PcdGet32 (PcdFspsRegionSize));
+    BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)FspoDxeBaseAddressInMem, PcdGet32 (PcdFspoDxeRegionSize));
+
+    //
+    // Register EndOfPei Nofity to run post FSP-S process.
+    //
+    Status = PeiServicesNotifyPpi (&mFspsWrapperEndOfPeiNotifyDesc);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return Status;
+}
+
+/**
+  This is the entrypoint of PEIM.
+
+  @param[in] FileHandle  Handle of the file being invoked.
+  @param[in] PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS if it completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+FspsWrapperPeimEntryPoint (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  DEBUG ((DEBUG_INFO, "FspsWrapperPeimEntryPoint\n"));
+
+ #ifndef COMPRESS_FSP_REGION
+  CopyMem ((VOID *)(UINTN)PcdGet32 (PcdFspoDxeBaseAddressInMemory), (VOID *)(UINTN)PcdGet32 (PcdFspoDxeBaseAddressInFlash), PcdGet32 (PcdFspoDxeRegionSize));
+  CopyMem ((VOID *)(UINTN)PcdGet32 (PcdFspsBaseAddressInMemory), (VOID *)(UINTN)PcdGet32 (PcdFspsBaseAddressInFlash), PcdGet32 (PcdFspsRegionSize));
+ #endif
+  BuildMemoryAllocationHob (
+    (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdFspsBaseAddressInMemory),
+    (UINT64)PcdGet32 (PcdFspsRegionSize),
+    EfiACPIMemoryNVS
+    );
+
+  BuildMemoryAllocationHob (
+    (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdFspoDxeBaseAddressInMemory),
+    (UINT64)PcdGet32 (PcdFspoDxeRegionSize),
+    EfiACPIMemoryNVS
+    );
+
+  if (PcdGet8 (PcdFspModeSelection) == 1) {
+    FspsWrapperInitApiMode ();
+  } else {
+    FspsWrapperInitDispatchMode ();
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
new file mode 100644
index 0000000000..f3c502f87d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
@@ -0,0 +1,91 @@
+## @file
+# FSP-S wrapper PEI Module
+#
+# This PEIM initialize FSP.
+# This will be invoked only once. It will call FspMemoryInit API,
+# register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
+# notify to call FspSiliconInit API.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = FspsWrapperPeim
+  FILE_GUID                      = 0D244DF9-6CE3-4133-A1CF-53200AB663AC
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = PEIM
+  ENTRY_POINT                    = FspsWrapperPeimEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[LibraryClasses]
+  PeimEntryPoint
+  PeiServicesLib
+  PeiServicesTablePointerLib
+  BaseLib
+  BaseMemoryLib
+  TimerLib
+  DebugLib
+  HobLib
+  MemoryAllocationLib
+  FspWrapperPlatformLib
+  FspWrapperHobProcessLib
+  CpuLib
+  UefiCpuLib
+  PeCoffGetEntryPointLib
+  PeCoffExtraActionLib
+  PerformanceLib
+  FspWrapperApiLib
+  FspWrapperApiTestLib
+  FspWrapperMultiPhaseProcessLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  SecurityPkg/SecurityPkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[Ppis]
+  gTopOfTemporaryRamPpiGuid                              ## PRODUCES
+  gFspSiliconInitDonePpiGuid                             ## PRODUCES
+  gEfiEndOfPeiSignalPpiGuid                              ## PRODUCES
+  gEfiTemporaryRamDonePpiGuid                            ## PRODUCES
+  gEfiPeiMemoryDiscoveredPpiGuid                         ## NOTIFY
+#-  gEdkiiTcgPpiGuid                                       ## NOTIFY
+  gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid    ## PRODUCES
+
+[Pcd]
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress    ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection      ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig  ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress64  ## CONSUMES
+  gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInFlash
+  gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInMemory
+  gFsp2WrapperTokenSpaceGuid.PcdFspoDxeBaseAddressInFlash
+  gFsp2WrapperTokenSpaceGuid.PcdFspoDxeBaseAddressInMemory
+  gFsp2WrapperTokenSpaceGuid.PcdFspsRegionSize
+  gFsp2WrapperTokenSpaceGuid.PcdFspoDxeRegionSize
+
+[Guids]
+  gFspHobGuid                           ## CONSUMES ## HOB
+  gFspApiPerformanceGuid                ## SOMETIMES_CONSUMES ## GUID
+  gFspExportedInterfaceHobGuid
+  gPlatformPkgTokenSpaceGuid
+
+[Sources]
+  FspsWrapperPeim.c
+
+[Depex]
+  gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspExportedInterfaceHob.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspExportedInterfaceHob.h
new file mode 100644
index 0000000000..66778b0143
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspExportedInterfaceHob.h
@@ -0,0 +1,146 @@
+/** @file
+  Implements FspExportedInterfaceHob.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_EXPORTED_INTERFACE_HOB_H
+#define FSP_EXPORTED_INTERFACE_HOB_H
+#include <Uefi.h>
+#include <FspsUpd.h>
+#define MAX_SMBIOS_TABLE_COUNT     20
+#define MAX_ACPI_SSDT_TABLE_COUNT  9
+
+#define FSP_TO_BOOTLOADER
+#define BOOTLOADER_TO_FSP
+#define IMPROPRIATE_ARCH
+
+typedef VOID  (EFIAPI *FSP_VIRTUAL_ADDRESS_CHANGE_CALLBACK)(FSPS_UPD *NewUpdAddress);
+typedef VOID  *(EFIAPI *BOOTLOADER_CONVERT_POINTER)(VOID *In);
+
+// Use "placeholder" for structure coherence under different CPU modes.
+// The GUID of HOB.
+extern EFI_GUID  gFspExportedInterfaceHobGuid;
+
+// Include goes here.
+
+#ifndef MDE_CPU_X64
+  #include <Ppi/Reset2.h>
+#else
+  #include <Protocol/SmbusHc.h>
+  #include <Protocol/SmmAccess2.h>
+  #include <Protocol/SmmControl2.h>
+  #include <Protocol/SmmBase2.h>
+  #include <Protocol/SmmCommunication.h>
+  #include <Protocol/MmCommunication2.h>
+  #include <Protocol/HiiDatabase.h>
+  #include <Protocol/HiiConfigRouting.h>
+  #include <Protocol/HiiString.h>
+  #include <Protocol/PciIo.h>
+  #include <Protocol/AmdPspFtpmProtocol.h>
+  #include <Uefi/UefiSpec.h>
+#endif
+
+#pragma pack (push,1)
+typedef struct _FSP_EXPORTED_INTERFACE_HOB FSP_EXPORTED_INTERFACE_HOB;
+#ifndef MDE_CPU_X64
+struct _FSP_EXPORTED_INTERFACE_HOB {
+  BOOTLOADER_TO_FSP VOID                  *SmmDriverVolume;
+  BOOTLOADER_TO_FSP UINT32                SmmDriverVolumeSize;
+  FSP_TO_BOOTLOADER VOID                  *PspFtpmPpi;
+  FSP_TO_BOOTLOADER VOID                  *PspFtpmFactoryResetPpi;
+  FSP_TO_BOOTLOADER EFI_PEI_RESET2_PPI    *Reset2Ppi;
+  IMPROPRIATE_ARCH UINT64                 SmbusProtocol;
+  IMPROPRIATE_ARCH UINT64                 SmmAccessProtocol;
+  IMPROPRIATE_ARCH UINT64                 SmmControl2Protocol;
+  IMPROPRIATE_ARCH UINT64                 PspCommonServiceProtocol;
+  IMPROPRIATE_ARCH UINT64                 ApobCommonServiceProtocol;
+  IMPROPRIATE_ARCH UINT64                 ApcbDxeServiceProtocol;
+  IMPROPRIATE_ARCH UINT64                 SmmBase2Protocol;
+  IMPROPRIATE_ARCH UINT64                 SmmCommunicationProtocol;
+  IMPROPRIATE_ARCH UINT64                 MmCommunication2Protocol;
+  IMPROPRIATE_ARCH UINT64                 FchResetSystem;
+  IMPROPRIATE_ARCH UINT64                 PcdAmdSmmCommunicationAddress;
+  IMPROPRIATE_ARCH UINT64                 PcdAmdS3LibPrivateDataAddress;
+  IMPROPRIATE_ARCH UINT64                 PcdAmdS3LibTableAddress;
+  IMPROPRIATE_ARCH UINT64                 PcdAmdS3LibTableSize;
+  IMPROPRIATE_ARCH UINT64                 SmbiosPointers[MAX_SMBIOS_TABLE_COUNT];
+  IMPROPRIATE_ARCH UINT64                 AcpiSsdtTables[MAX_ACPI_SSDT_TABLE_COUNT];
+  IMPROPRIATE_ARCH UINT64                 AcpiTpm2Table;
+  IMPROPRIATE_ARCH UINT64                 AcpiCratTable;
+  IMPROPRIATE_ARCH UINT64                 AcpiCditTable;
+  IMPROPRIATE_ARCH UINT64                 AcpiIvrsTable;
+  IMPROPRIATE_ARCH UINT64                 VirtualAddressChangeCallback;
+  IMPROPRIATE_ARCH UINT64                 FinalMemoryMap;
+  IMPROPRIATE_ARCH UINT64                 FinalMemoryMapSize;
+  IMPROPRIATE_ARCH UINT64                 FinalMemoryDescriptorSize;
+  IMPROPRIATE_ARCH UINT64                 ConvertPointer;
+  IMPROPRIATE_ARCH UINT64                 ExportedInterfaceHobAddressAfterNotifyPhase;
+  IMPROPRIATE_ARCH UINT64                 PspPlatformProtocol;
+  IMPROPRIATE_ARCH UINT64                 GetVariable;
+  IMPROPRIATE_ARCH UINT64                 GetNextVariableName;
+  IMPROPRIATE_ARCH UINT64                 QueryVariableInfo;
+  IMPROPRIATE_ARCH UINT64                 SetVariable;
+  IMPROPRIATE_ARCH UINT64                 HiiProtocol;
+  IMPROPRIATE_ARCH UINT64                 HiiStringProtocol;
+  IMPROPRIATE_ARCH UINT64                 HiiConfigRoutingProtocol;
+  IMPROPRIATE_ARCH UINT64                 S3BootScriptTablePrivateSmmDataPtr;
+  IMPROPRIATE_ARCH UINT64                 S3BootScriptTablePrivateDataPtr;
+  IMPROPRIATE_ARCH UINT64                 EfiPciIoProtocol;
+  IMPROPRIATE_ARCH UINT64                 EfiPciIoProtocolCount;
+  IMPROPRIATE_ARCH UINT64                 PspFtpmProtocol;
+};
+
+#else
+struct _FSP_EXPORTED_INTERFACE_HOB {
+  IMPROPRIATE_ARCH UINT32                                  SmmDriverVolume;
+  IMPROPRIATE_ARCH UINT32                                  SmmDriverVolumeSize;
+  IMPROPRIATE_ARCH UINT32                                  PspFtpmPpi;
+  IMPROPRIATE_ARCH UINT32                                  PspFtpmFactoryResetPpi;
+  IMPROPRIATE_ARCH UINT32                                  Reset2Ppi;
+  FSP_TO_BOOTLOADER EFI_SMBUS_HC_PROTOCOL                  *SmbusProtocol;
+  FSP_TO_BOOTLOADER EFI_SMM_ACCESS2_PROTOCOL               *SmmAccessProtocol;
+  FSP_TO_BOOTLOADER EFI_SMM_CONTROL2_PROTOCOL              *SmmControl2Protocol;
+  FSP_TO_BOOTLOADER VOID                                   *PspCommonServiceProtocol;
+  FSP_TO_BOOTLOADER VOID                                   *ApobCommonServiceProtocol;
+  FSP_TO_BOOTLOADER VOID                                   *ApcbDxeServiceProtocol;
+  FSP_TO_BOOTLOADER EFI_SMM_BASE2_PROTOCOL                 *SmmBase2Protocol;
+  FSP_TO_BOOTLOADER EFI_SMM_COMMUNICATION_PROTOCOL         *SmmCommunicationProtocol;
+  FSP_TO_BOOTLOADER EFI_MM_COMMUNICATION2_PROTOCOL         *MmCommunication2Protocol;
+  FSP_TO_BOOTLOADER EFI_RESET_SYSTEM                       FchResetSystem;
+  FSP_TO_BOOTLOADER UINT64                                 PcdAmdSmmCommunicationAddress;
+  FSP_TO_BOOTLOADER UINT64                                 PcdAmdS3LibPrivateDataAddress;
+  FSP_TO_BOOTLOADER UINT64                                 PcdAmdS3LibTableAddress;
+  FSP_TO_BOOTLOADER UINT64                                 PcdAmdS3LibTableSize;
+  FSP_TO_BOOTLOADER VOID                                   *SmbiosPointers[MAX_SMBIOS_TABLE_COUNT];
+  FSP_TO_BOOTLOADER VOID                                   *AcpiSsdtTables[MAX_ACPI_SSDT_TABLE_COUNT];
+  FSP_TO_BOOTLOADER VOID                                   *AcpiTpm2Table;
+  FSP_TO_BOOTLOADER VOID                                   *AcpiCratTable;
+  FSP_TO_BOOTLOADER VOID                                   *AcpiCditTable;
+  FSP_TO_BOOTLOADER VOID                                   *AcpiIvrsTable;
+  FSP_TO_BOOTLOADER FSP_VIRTUAL_ADDRESS_CHANGE_CALLBACK    VirtualAddressChangeCallback;
+  FSP_TO_BOOTLOADER VOID                                   *FinalMemoryMap;
+  FSP_TO_BOOTLOADER UINT64                                 FinalMemoryMapSize;
+  FSP_TO_BOOTLOADER UINT64                                 FinalMemoryDescriptorSize;
+  BOOTLOADER_TO_FSP BOOTLOADER_CONVERT_POINTER             ConvertPointer;
+  FSP_TO_BOOTLOADER FSP_EXPORTED_INTERFACE_HOB             *ExportedInterfaceHobAddressAfterNotifyPhase;
+  BOOTLOADER_TO_FSP VOID                                   *PspPlatformProtocol;
+  BOOTLOADER_TO_FSP EFI_GET_VARIABLE                       GetVariable;
+  BOOTLOADER_TO_FSP EFI_GET_NEXT_VARIABLE_NAME             GetNextVariableName;
+  BOOTLOADER_TO_FSP EFI_QUERY_VARIABLE_INFO                QueryVariableInfo;
+  BOOTLOADER_TO_FSP EFI_SET_VARIABLE                       SetVariable;
+  BOOTLOADER_TO_FSP EFI_HII_DATABASE_PROTOCOL              *HiiProtocol;
+  BOOTLOADER_TO_FSP EFI_HII_STRING_PROTOCOL                *HiiStringProtocol;
+  BOOTLOADER_TO_FSP EFI_HII_CONFIG_ROUTING_PROTOCOL        *HiiConfigRoutingProtocol;
+  FSP_TO_BOOTLOADER UINT64                                 S3BootScriptTablePrivateSmmDataPtr;
+  FSP_TO_BOOTLOADER UINT64                                 S3BootScriptTablePrivateDataPtr;
+  BOOTLOADER_TO_FSP EFI_PCI_IO_PROTOCOL                    **EfiPciIoProtocol;
+  BOOTLOADER_TO_FSP UINT64                                 EfiPciIoProtocolCount;
+  FSP_TO_BOOTLOADER PSP_FTPM_PROTOCOL                      *PspFtpmProtocol;
+};
+
+#endif
+#pragma pack (pop)
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspMemoryRegionHob.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspMemoryRegionHob.h
new file mode 100644
index 0000000000..3319cad3bc
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspMemoryRegionHob.h
@@ -0,0 +1,15 @@
+/** @file
+  Implements FspMemoryRegionHob.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#pragma pack(push,1)
+typedef struct {
+  EFI_PHYSICAL_ADDRESS    BeginAddress;
+  EFI_PHYSICAL_ADDRESS    Length;
+} FSP_MEMORY_REGION_HOB;
+#pragma pack(pop)
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspSmmDataExchangeBuffer.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspSmmDataExchangeBuffer.h
new file mode 100644
index 0000000000..1eaa187bb8
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspSmmDataExchangeBuffer.h
@@ -0,0 +1,24 @@
+/** @file
+  Implements FspSmmDataExchangeBuffer.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Protocol/GlobalNvsArea.h>
+#include <Protocol/Tcg2Protocol.h>
+#include <Protocol/TcgService.h>
+#include <Protocol/Variable.h>
+
+// You may define a customized callback function whenever the exchange buffer is updated.
+
+typedef EFI_STATUS (EFIAPI *DETECT_AND_INSTALL_NEW_PROTOCOL)(VOID);
+
+#pragma pack(push,1)
+typedef struct _FSP_SMM_DATA_EXCHANGE_BUFFER {
+  EFI_GLOBAL_NVS_AREA_PROTOCOL    *NvsAreaProtocol;               // gEfiGlobalNvsAreaProtocolGuid
+  EFI_TCG2_PROTOCOL               *EfiTcg2Protocol;               // gEfiTcg2ProtocolGuid
+} FSP_SMM_DATA_EXCHANGE_BUFFER;
+#pragma pack(pop)
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspUpd.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspUpd.h
new file mode 100644
index 0000000000..1190437bd9
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspUpd.h
@@ -0,0 +1,23 @@
+/** @file
+  Implements FspUpd.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSPUPD_H_
+#define FSPUPD_H_
+
+#ifdef USE_EDKII_HEADER_FILE
+  #include <FspEas.h>
+  #include <stdint.h>
+#else
+  #include <fsp_h_c99.h>
+#endif
+
+#define FSPM_UPD_SIGNATURE  0x4D5F48474F474E56                     /* 'VNGOGH_M' */
+
+#define FSPS_UPD_SIGNATURE  0x535F48474F474E56                     /* 'VNGOGH_S' */
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspmUpd.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspmUpd.h
new file mode 100644
index 0000000000..8cadbe430a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspmUpd.h
@@ -0,0 +1,66 @@
+/** @file
+  Implements FspmUpd.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSPMUPD_H_
+#define FSPMUPD_H_
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+/** Fsp M Configuration
+**/
+typedef struct {
+  /** Offset 0x0040**/ UINT32    bert_size;
+  /** Offset 0x0044**/ UINT32    tseg_size;
+  /** Offset 0x0048**/ UINT32    dxio_descriptor_table_pointer;
+  /** Offset 0x004C**/ UINT32    pcie_reset_function_pointer;
+  /** Offset 0x0050**/ UINT32    ddi_descriptor_table_pointer;
+  /** Offset 0x0054**/ UINT32    temp_memory_base_addr;
+  /** Offset 0x0058**/ UINT32    temp_memory_size;
+  /** Offset 0x005C**/ UINT32    fsp_o_pei_volume_address;
+  /** Offset 0x0060**/ UINT32    fsp_o_pei_upd_address;
+  /** Offset 0x0064**/ UINT32    pei_reset_ppi_addr;
+  /** Offset 0x0068**/ UINT32    resource_size_for_each_rb_ptr;
+  /** Offset 0x006C**/ UINT32    resource_size_for_each_rb_size;
+  /** Offset 0x0070**/ UINT32    total_number_of_root_bridges_ptr;
+  /** Offset 0x0074**/ UINT32    total_number_of_root_bridges_size;
+  /** Offset 0x0078**/ UINT32    amd_pbs_setup_ptr;
+  /** Offset 0x007C**/ UINT32    amd_pbs_setup_size;
+  /** Offset 0x0080**/ UINT32    ap_sync_flag_nv_ptr;
+  /** Offset 0x0084**/ UINT32    ap_sync_flag_nv_size;
+  /** Offset 0x0088**/ UINT8     DbgFchUsbUsb0DrdMode;
+  /** Offset 0x0089**/ UINT8     DbgFchUsbUsb2DrdMode;
+  /** Offset 0x008A**/ UINT32    CmnGnbGfxUmaFrameBufferSize;
+  /** Offset 0x008E**/ UINT8     CmnGnbNbIOMMU;
+  /** Offset 0x008F**/ UINT32    DbgFastPPTLimit;
+  /** Offset 0x0093**/ UINT32    DbgSlowPPTLimit;
+  /** Offset 0x0097**/ UINT32    CmnCpuVoltageOffset;
+  /** Offset 0x009B**/ UINT32    CmnGpuVoltageOffset;
+  /** Offset 0x009F**/ UINT32    CmnSocVoltageOffset;
+  /** Offset 0x00A3**/ UINT8     CmnGnbGfxUmaMode;
+  /** Offset 0x00A4**/ UINT8     CmnFchI2C0Config;
+  /** Offset 0x00A5**/ UINT8     CmnFchI2C1Config;
+  /** Offset 0x00A6**/ UINT8     CmnFchI2C2Config;
+  /** Offset 0x00A7**/ UINT8     CmnFchI2C3Config;
+  /** Offset 0x00A8**/ UINT32    ids_nv_table_address;
+  /** Offset 0x00AC**/ UINT32    ids_nv_table_size;
+  /** Offset 0x00B0**/ UINT16    UpdTerminator;
+} FSP_M_CONFIG;
+
+/** Fsp M UPD Configuration
+**/
+typedef struct {
+  /** Offset 0x0000**/ FSP_UPD_HEADER    FspUpdHeader;
+  /** Offset 0x0020**/ FSPM_ARCH_UPD     FspmArchUpd;
+  /** Offset 0x0040**/ FSP_M_CONFIG      FspmConfig;
+} FSPM_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspsUpd.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspsUpd.h
new file mode 100644
index 0000000000..034622bc09
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FspsUpd.h
@@ -0,0 +1,45 @@
+/** @file
+  Implements FspsUpd.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSPSUPD_H_
+#define FSPSUPD_H_
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+typedef struct {
+  /** Offset 0x0030**/ UINT32    page_address_below_1mb;
+  /** Offset 0x0034**/ UINT32    smram_hob_base_addr;
+  /** Offset 0x0038**/ UINT32    smram_hob_size;
+  /** Offset 0x003C**/ UINT32    nv_storage_variable_base;
+  /** Offset 0x0040**/ UINT32    nv_storage_variable_size;
+  /** Offset 0x0044**/ UINT32    nv_storage_ftw_working_base;
+  /** Offset 0x0048**/ UINT32    nv_storage_ftw_working_size;
+  /** Offset 0x004C**/ UINT32    nv_storage_ftw_spare_base;
+  /** Offset 0x0050**/ UINT32    nv_storage_ftw_spare_size;
+  /** Offset 0x0054**/ UINT32    dgpu_ssid;
+  /** Offset 0x0058**/ UINT32    dgpu_audio_ssid;
+  /** Offset 0x005C**/ UINT32    smram_hob_descriptor_base_addr;
+  /** Offset 0x0060**/ UINT32    smram_hob_descriptor_size;
+  /** Offset 0x0064**/ UINT64    smm_data_buffer_address;
+  /** Offset 0x006C**/ UINT32    fsp_o_dxe_volume_address;
+  /** Offset 0x0070**/ UINT32    fsp_o_dxe_upd_address;
+  /** Offset 0x0074**/ UINT16    UpdTerminator;
+} FSP_S_CONFIG;
+
+/** Fsp S UPD Configuration
+**/
+typedef struct {
+  /** Offset 0x0000**/ FSP_UPD_HEADER    FspUpdHeader;
+  /** Offset 0x0030**/ FSP_S_CONFIG      FspsConfig;
+} FSPS_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FsptUpd.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FsptUpd.h
new file mode 100644
index 0000000000..847e619ae6
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/FsptUpd.h
@@ -0,0 +1,18 @@
+/** @file
+  Implements FsptUpd.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSPTUPD_H_
+#define FSPTUPD_H_
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+#pragma pack()
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspMeasurementLib.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspMeasurementLib.h
new file mode 100644
index 0000000000..578c4876e4
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspMeasurementLib.h
@@ -0,0 +1,41 @@
+/** @file
+  This library is used by FSP modules to measure data to TPM.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2020, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_MEASUREMENT_LIB_H_
+#define FSP_MEASUREMENT_LIB_H_
+
+#define FSP_MEASURE_FSP     BIT0
+#define FSP_MEASURE_FSPT    BIT1
+#define FSP_MEASURE_FSPM    BIT2
+#define FSP_MEASURE_FSPS    BIT3
+#define FSP_MEASURE_FSPUPD  BIT31
+
+/**
+  Measure a FSP FirmwareBlob.
+
+  @param[in]  PcrIndex                PCR Index.
+  @param[in]  Description             Description for this FirmwareBlob.
+  @param[in]  FirmwareBlobBase        Base address of this FirmwareBlob.
+  @param[in]  FirmwareBlobLength      Size in bytes of this FirmwareBlob.
+
+  @retval EFI_SUCCESS           Operation completed successfully.
+  @retval EFI_UNSUPPORTED       TPM device not available.
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
+*/
+EFI_STATUS
+EFIAPI
+MeasureFspFirmwareBlob (
+  IN UINT32                PcrIndex,
+  IN CHAR8                 *Description OPTIONAL,
+  IN EFI_PHYSICAL_ADDRESS  FirmwareBlobBase,
+  IN UINT64                FirmwareBlobLength
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiLib.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiLib.h
new file mode 100644
index 0000000000..913cdbd0d3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiLib.h
@@ -0,0 +1,82 @@
+/** @file
+  Provide FSP wrapper API related function.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_WRAPPER_API_LIB_H_
+#define FSP_WRAPPER_API_LIB_H_
+
+#include <FspEas.h>
+
+/**
+  Find FSP header pointer.
+
+  @param[in] FlashFvFspBase Flash address of FSP FV.
+
+  @return FSP header pointer.
+**/
+FSP_INFO_HEADER *
+EFIAPI
+FspFindFspHeader (
+  IN EFI_PHYSICAL_ADDRESS  FlashFvFspBase
+  );
+
+/**
+  Call FSP API - FspNotifyPhase.
+
+  @param[in] NotifyPhaseParams Address pointer to the NOTIFY_PHASE_PARAMS structure.
+
+  @return EFI status returned by FspNotifyPhase API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspNotifyPhase (
+  IN NOTIFY_PHASE_PARAMS  *NotifyPhaseParams
+  );
+
+/**
+  Call FSP API - FspMemoryInit.
+
+  @param[in]  FspmUpdDataPtr          Pointer to the FSPM_UPD data structure.
+  @param[out] HobListPtr              Pointer to receive the address of the HOB list.
+
+  @return EFI status returned by FspMemoryInit API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspMemoryInit (
+  IN VOID   *FspmUpdDataPtr,
+  OUT VOID  **HobListPtr
+  );
+
+/**
+  Call FSP API - TempRamExit.
+
+  @param[in] TempRamExitParam    Address pointer to the TempRamExit parameters structure.
+
+  @return EFI status returned by TempRamExit API.
+**/
+EFI_STATUS
+EFIAPI
+CallTempRamExit (
+  IN VOID  *TempRamExitParam
+  );
+
+/**
+  Call FSP API - FspSiliconInit.
+
+  @param[in] FspsUpdDataPtr     Pointer to the FSPS_UPD data structure.
+
+  @return EFI status returned by FspSiliconInit API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspSiliconInit (
+  IN VOID  *FspsUpdDataPtr
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiTestLib.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiTestLib.h
new file mode 100644
index 0000000000..164de56ce9
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperApiTestLib.h
@@ -0,0 +1,56 @@
+/** @file
+  Provide FSP wrapper API test related function.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_WRAPPER_API_TEST_LIB_H_
+#define FSP_WRAPPER_API_TEST_LIB_H_
+
+#include <PiPei.h>
+
+/**
+  Test the output of FSP API - FspMemoryInit.
+
+  @param[in]  FspmUpdDataPtr Address pointer to the FSP_MEMORY_INIT_PARAMS structure.
+  @param[in]  HobListPtr     Address of the HobList pointer.
+
+  @return test result on output of FspMemoryInit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspMemoryInitApiOutput (
+  IN  VOID  *FspmUpdDataPtr,
+  IN  VOID  **HobListPtr
+  );
+
+/**
+  Test the output of FSP API - TempRamExit.
+
+  @param[in] TempRamExitParam    Address pointer to the TempRamExit parameters structure.
+
+  @return test result on output of TempRamExit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspTempRamExitApiOutput (
+  IN VOID  *TempRamExitParam
+  );
+
+/**
+  Test the output of FSP API - FspSiliconInit.
+
+  @param[in] FspsUpdDataPtr Address pointer to the Silicon Init parameters structure.
+
+  @return test result on output of FspSiliconInit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspSiliconInitApiOutput (
+  IN  VOID  *FspsUpdDataPtr
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperHobProcessLib.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperHobProcessLib.h
new file mode 100644
index 0000000000..9a78041631
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperHobProcessLib.h
@@ -0,0 +1,39 @@
+/** @file
+  Provide FSP wrapper hob process related function.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_WRAPPER_HOB_PROCESS_LIB_H_
+#define FSP_WRAPPER_HOB_PROCESS_LIB_H_
+
+/**
+  Post FSP-M HOB process for Memory Resource Descriptor.
+
+  @param[in] FspHobList  Pointer to the HOB data structure produced by FSP.
+
+  @return If platform process the FSP hob list successfully.
+**/
+EFI_STATUS
+EFIAPI
+PostFspmHobProcess (
+  IN VOID  *FspHobList
+  );
+
+/**
+  Post FSP-S HOB process (not Memory Resource Descriptor).
+
+  @param[in] FspHobList  Pointer to the HOB data structure produced by FSP.
+
+  @return If platform process the FSP hob list successfully.
+**/
+EFI_STATUS
+EFIAPI
+PostFspsHobProcess (
+  IN VOID  *FspHobList
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperMultiPhaseProcessLib.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperMultiPhaseProcessLib.h
new file mode 100644
index 0000000000..0aa17b53a5
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperMultiPhaseProcessLib.h
@@ -0,0 +1,45 @@
+/** @file
+  Provide FSP wrapper MultiPhase handling functions.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_WRAPPER_MULTI_PHASE_PROCESS_LIB_H_
+#define FSP_WRAPPER_MULTI_PHASE_PROCESS_LIB_H_
+
+/**
+  FSP Wrapper Variable Request Handler
+
+  @param[in] FspHobListPtr        - Pointer to FSP HobList (valid after FSP-M completed)
+  @param[in] ComponentIndex       - FSP Component which executing MultiPhase initialization.
+
+  @retval EFI_UNSUPPORTED   FSP Wrapper cannot support the specific variable request
+  @retval EFI_STATUS        Return FSP returned status
+
+**/EFI_STATUS
+EFIAPI
+FspWrapperVariableRequestHandler (
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex
+  );
+
+/**
+  FSP Wrapper MultiPhase Handler
+
+  @param[in] FspHobListPtr        - Pointer to FSP HobList (valid after FSP-M completed)
+  @param[in] ComponentIndex       - FSP Component which executing MultiPhase initialization.
+
+  @retval EFI_STATUS        Always return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+FspWrapperMultiPhaseHandler (
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformLib.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformLib.h
new file mode 100644
index 0000000000..860295b70d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformLib.h
@@ -0,0 +1,81 @@
+/** @file
+  Provide FSP wrapper platform related function.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_WRAPPER_PLATFORM_LIB_H_
+#define FSP_WRAPPER_PLATFORM_LIB_H_
+
+/**
+  This function overrides the default configurations in the FSP-M UPD data region.
+
+  @param[in,out] FspUpdRgnPtr   A pointer to the UPD data region data structure.
+
+**/
+VOID
+EFIAPI
+UpdateFspmUpdData (
+  IN OUT VOID  *FspUpdRgnPtr
+  );
+
+/**
+  This function overrides the default configurations in the FSP-S UPD data region.
+
+  @param[in,out] FspUpdRgnPtr   A pointer to the UPD data region data structure.
+
+**/
+VOID
+EFIAPI
+UpdateFspsUpdData (
+  IN OUT VOID  *FspUpdRgnPtr
+  );
+
+/**
+  Update TempRamExit parameter.
+
+  @note At this point, memory is ready, PeiServices are available to use.
+
+  @return TempRamExit parameter.
+**/
+VOID *
+EFIAPI
+UpdateTempRamExitParam (
+  VOID
+  );
+
+/**
+  Get S3 PEI memory information.
+
+  @note At this point, memory is ready, and PeiServices are available to use.
+  Platform can get some data from SMRAM directly.
+
+  @param[out] S3PeiMemSize  PEI memory size to be installed in S3 phase.
+  @param[out] S3PeiMemBase  PEI memory base to be installed in S3 phase.
+
+  @return If S3 PEI memory information is got successfully.
+**/
+EFI_STATUS
+EFIAPI
+GetS3MemoryInfo (
+  OUT UINT64                *S3PeiMemSize,
+  OUT EFI_PHYSICAL_ADDRESS  *S3PeiMemBase
+  );
+
+/**
+  Perform platform related reset in FSP wrapper.
+
+  This function will reset the system with requested ResetType.
+
+  @param[in] FspStatusResetType  The type of reset the platform has to perform.
+**/
+VOID
+EFIAPI
+CallFspWrapperResetSystem (
+  IN EFI_STATUS  FspStatusResetType
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformMultiPhaseLib.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformMultiPhaseLib.h
new file mode 100644
index 0000000000..8e16ddb719
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Library/FspWrapperPlatformMultiPhaseLib.h
@@ -0,0 +1,31 @@
+/** @file
+  Provide FSP wrapper Platform MultiPhase handling functions.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_WRAPPER_PLATFORM_MULTI_PHASE_LIB_H_
+#define FSP_WRAPPER_PLATFORM_MULTI_PHASE_LIB_H_
+
+/**
+  FSP Wrapper Platform MultiPhase Handler
+
+  @param[in] FspHobListPtr        - Pointer to FSP HobList (valid after FSP-M completed)
+  @param[in] ComponentIndex       - FSP Component which executing MultiPhase initialization.
+  @param[in] PhaseIndex           - Indicates current execution phase of FSP MultiPhase initialization.
+
+  @retval EFI_STATUS        Always return EFI_SUCCESS
+
+**/
+VOID
+EFIAPI
+FspWrapperPlatformMultiPhaseHandler (
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex,
+  IN UINT32    PhaseIndex
+  );
+
+#endif //FSP_WRAPPER_PLATFORM_MULTI_PHASE_LIB_H_
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/MultiPhaseSiPhases.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/MultiPhaseSiPhases.h
new file mode 100644
index 0000000000..a0b1ff537b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/MultiPhaseSiPhases.h
@@ -0,0 +1,19 @@
+/** @file
+  Implements MultiPhaseSiPhases.h
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MULTI_PHASE_SI_PHASES_H_
+#define MULTI_PHASE_SI_PHASES_H_
+
+typedef enum {
+  EnumMultiPhaseAmdCpmDxeTableReadyPhase = 1,  // In FSP Doc, the index starts from 1.
+  EnumMultiPhaseAmdSmmCoreBroughtUpPhase,
+  EnumMultiPhaseAmdRuntimeServicesReadyPhase,
+  // ......
+  EnumMultiPhaseAmdMaxPhase
+} AMD_MULTI_PHASE_SI_PHASES_H;
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/FspSiliconInitDone.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/FspSiliconInitDone.h
new file mode 100644
index 0000000000..649fcdc8e9
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/FspSiliconInitDone.h
@@ -0,0 +1,38 @@
+/** @file
+  Provides the services to return FSP hob list.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_SILICON_INIT_DONE_H_
+#define FSP_SILICON_INIT_DONE_H_
+
+typedef struct _FSP_SILICON_INIT_DONE_PPI FSP_SILICON_INIT_DONE_PPI;
+
+/**
+  Return Hob list produced by FSP.
+
+  @param[in]  PeiServices  The pointer to the PEI Services Table.
+  @param[in]  This         The pointer to this instance of this PPI.
+  @param[out] FspHobList   The pointer to Hob list produced by FSP.
+
+  @return EFI_SUCCESS FReturn Hob list produced by FSP successfully.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_SILICON_INIT_DONE_GET_FSP_HOB_LIST)(
+  IN  CONST EFI_PEI_SERVICES         **PeiServices,
+  IN  FSP_SILICON_INIT_DONE_PPI      *This,
+  OUT VOID                           **FspHobList
+  );
+
+struct _FSP_SILICON_INIT_DONE_PPI {
+  FSP_SILICON_INIT_DONE_GET_FSP_HOB_LIST    GetFspHobList;
+};
+
+extern EFI_GUID  gFspSiliconInitDonePpiGuid;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/TopOfTemporaryRam.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/TopOfTemporaryRam.h
new file mode 100644
index 0000000000..ab2815fc07
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Ppi/TopOfTemporaryRam.h
@@ -0,0 +1,15 @@
+/** @file
+  Provides the pointer to top of temporary ram.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef TOP_OF_TEMPORARY_RAM_H_
+#define TOP_OF_TEMPORARY_RAM_H_
+
+extern EFI_GUID  gTopOfTemporaryRamPpiGuid;
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf
new file mode 100644
index 0000000000..48eb4991dd
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf
@@ -0,0 +1,54 @@
+## @file
+#  Provides FSP measurement functions.
+#
+#  This library provides MeasureFspFirmwareBlob() to measure FSP binary.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FspMeasurementLib
+  FILE_GUID                      = 890B12B4-56CC-453E-B062-4597FC6D3D8C
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FspMeasurementLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  FspMeasurementLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  PrintLib
+  PcdLib
+  PeiServicesLib
+  PeiServicesTablePointerLib
+  FspWrapperApiLib
+  TcgEventLogRecordLib
+  HashLib
+
+[Ppis]
+  gEdkiiTcgPpiGuid                                                   ## CONSUMES
+
+[Pcd]
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig            ## CONSUMES
+  gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInMemory                ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision        ## CONSUMES
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/FspMeasurementLib.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/FspMeasurementLib.c
new file mode 100644
index 0000000000..9a9368bb75
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspMeasurementLib/FspMeasurementLib.c
@@ -0,0 +1,254 @@
+/** @file
+  This library is used by FSP modules to measure data to TPM.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2020, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/TpmMeasurementLib.h>
+#include <Library/FspMeasurementLib.h>
+#include <Library/TcgEventLogRecordLib.h>
+#include <Library/HashLib.h>
+
+#include <Ppi/Tcg.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+
+/**
+  Tpm measure and log data, and extend the measurement result into a specific PCR.
+
+  @param[in]  PcrIndex         PCR Index.
+  @param[in]  EventType        Event type.
+  @param[in]  EventLog         Measurement event log.
+  @param[in]  LogLen           Event log length in bytes.
+  @param[in]  HashData         The start of the data buffer to be hashed, extended.
+  @param[in]  HashDataLen      The length, in bytes, of the buffer referenced by HashData
+  @param[in]  Flags            Bitmap providing additional information.
+
+  @retval EFI_SUCCESS           Operation completed successfully.
+  @retval EFI_UNSUPPORTED       TPM device not available.
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+TpmMeasureAndLogDataWithFlags (
+  IN UINT32  PcrIndex,
+  IN UINT32  EventType,
+  IN VOID    *EventLog,
+  IN UINT32  LogLen,
+  IN VOID    *HashData,
+  IN UINT64  HashDataLen,
+  IN UINT64  Flags
+  )
+{
+  EFI_STATUS         Status;
+  EDKII_TCG_PPI      *TcgPpi;
+  TCG_PCR_EVENT_HDR  TcgEventHdr;
+
+  Status = PeiServicesLocatePpi (
+             &gEdkiiTcgPpiGuid,
+             0,
+             NULL,
+             (VOID **)&TcgPpi
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  TcgEventHdr.PCRIndex  = PcrIndex;
+  TcgEventHdr.EventType = EventType;
+  TcgEventHdr.EventSize = LogLen;
+
+  Status = TcgPpi->HashLogExtendEvent (
+                     TcgPpi,
+                     Flags,
+                     HashData,
+                     (UINTN)HashDataLen,
+                     &TcgEventHdr,
+                     EventLog
+                     );
+  return Status;
+}
+
+/**
+  Measure a FSP FirmwareBlob.
+
+  @param[in]  Description             Description for this FirmwareBlob.
+  @param[in]  FirmwareBlobBase        Base address of this FirmwareBlob.
+  @param[in]  FirmwareBlobLength      Size in bytes of this FirmwareBlob.
+  @param[in]  CfgRegionOffset         Configuration region offset in bytes.
+  @param[in]  CfgRegionSize           Configuration region in bytes.
+
+  @retval EFI_SUCCESS           Operation completed successfully.
+  @retval EFI_UNSUPPORTED       TPM device not available.
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MeasureFspFirmwareBlobWithCfg (
+  IN CHAR8                 *Description OPTIONAL,
+  IN EFI_PHYSICAL_ADDRESS  FirmwareBlobBase,
+  IN UINT64                FirmwareBlobLength,
+  IN UINT32                CfgRegionOffset,
+  IN UINT32                CfgRegionSize
+  )
+{
+  EFI_PLATFORM_FIRMWARE_BLOB      FvBlob, UpdBlob;
+  PLATFORM_FIRMWARE_BLOB2_STRUCT  FvBlob2, UpdBlob2;
+  VOID                            *FvName;
+  UINT32                          FvEventType;
+  VOID                            *FvEventLog, *UpdEventLog;
+  UINT32                          FvEventLogSize, UpdEventLogSize;
+  EFI_STATUS                      Status;
+  HASH_HANDLE                     HashHandle;
+  UINT8                           *HashBase;
+  UINTN                           HashSize;
+  TPML_DIGEST_VALUES              DigestList;
+
+  FvName = TpmMeasurementGetFvName (FirmwareBlobBase, FirmwareBlobLength);
+
+  if (((Description != NULL) || (FvName != NULL)) &&
+      (PcdGet32 (PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105))
+  {
+    if (Description != NULL) {
+      AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDescription), "%a", Description);
+      AsciiSPrint ((CHAR8 *)UpdBlob2.BlobDescription, sizeof (UpdBlob2.BlobDescription), "%aUDP", Description);
+    } else {
+      AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof (FvBlob2.BlobDescription), "Fv(%g)", FvName);
+      AsciiSPrint ((CHAR8 *)UpdBlob2.BlobDescription, sizeof (UpdBlob2.BlobDescription), "(%g)UDP", FvName);
+    }
+
+    FvBlob2.BlobDescriptionSize = sizeof (FvBlob2.BlobDescription);
+    FvBlob2.BlobBase            = FirmwareBlobBase;
+    FvBlob2.BlobLength          = FirmwareBlobLength;
+    FvEventType                 = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
+    FvEventLog                  = &FvBlob2;
+    FvEventLogSize              = sizeof (FvBlob2);
+
+    UpdBlob2.BlobDescriptionSize = sizeof (UpdBlob2.BlobDescription);
+    UpdBlob2.BlobBase            = CfgRegionOffset;
+    UpdBlob2.BlobLength          = CfgRegionSize;
+    UpdEventLog                  = &UpdBlob2;
+    UpdEventLogSize              = sizeof (UpdBlob2);
+  } else {
+    FvBlob.BlobBase   = FirmwareBlobBase;
+    FvBlob.BlobLength = FirmwareBlobLength;
+    FvEventType       = EV_EFI_PLATFORM_FIRMWARE_BLOB;
+    FvEventLog        = &FvBlob;
+    FvEventLogSize    = sizeof (FvBlob);
+
+    UpdBlob.BlobBase   = CfgRegionOffset;
+    UpdBlob.BlobLength = CfgRegionSize;
+    UpdEventLog        = &UpdBlob;
+    UpdEventLogSize    = sizeof (UpdBlob);
+  }
+
+  /** Initialize a SHA hash context. **/
+  Status = HashStart (&HashHandle);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "HashStart failed - %r\n", Status));
+    return Status;
+  }
+
+  /** Hash FSP binary before UDP **/
+  HashBase = (UINT8 *)(UINTN)FirmwareBlobBase;
+  HashSize = (UINTN)CfgRegionOffset;
+  Status   = HashUpdate (HashHandle, HashBase, HashSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "HashUpdate failed - %r\n", Status));
+    return Status;
+  }
+
+  /** Hash FSP binary after UDP **/
+  HashBase = (UINT8 *)(UINTN)FirmwareBlobBase + CfgRegionOffset + CfgRegionSize;
+  HashSize = (UINTN)(FirmwareBlobLength - CfgRegionOffset - CfgRegionSize);
+  Status   = HashUpdate (HashHandle, HashBase, HashSize);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "HashUpdate failed - %r\n", Status));
+    return Status;
+  }
+
+  /** Finalize the SHA hash. **/
+  Status = HashCompleteAndExtend (HashHandle, 0, NULL, 0, &DigestList);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "HashCompleteAndExtend failed - %r\n", Status));
+    return Status;
+  }
+
+  Status = TpmMeasureAndLogDataWithFlags (
+             0,
+             FvEventType,
+             FvEventLog,
+             FvEventLogSize,
+             (UINT8 *)&DigestList,
+             (UINTN)sizeof (DigestList),
+             EDKII_TCG_PRE_HASH_LOG_ONLY
+             );
+
+  Status = TpmMeasureAndLogData (
+             1,
+             EV_PLATFORM_CONFIG_FLAGS,
+             UpdEventLog,
+             UpdEventLogSize,
+             (UINT8 *)(UINTN)FirmwareBlobBase + CfgRegionOffset,
+             CfgRegionSize
+             );
+
+  return Status;
+}
+
+/**
+  Measure a FSP FirmwareBlob.
+
+  @param[in]  PcrIndex                PCR Index.
+  @param[in]  Description             Description for this FirmwareBlob.
+  @param[in]  FirmwareBlobBase        Base address of this FirmwareBlob.
+  @param[in]  FirmwareBlobLength      Size in bytes of this FirmwareBlob.
+
+  @retval EFI_SUCCESS           Operation completed successfully.
+  @retval EFI_UNSUPPORTED       TPM device not available.
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+MeasureFspFirmwareBlob (
+  IN UINT32                PcrIndex,
+  IN CHAR8                 *Description OPTIONAL,
+  IN EFI_PHYSICAL_ADDRESS  FirmwareBlobBase,
+  IN UINT64                FirmwareBlobLength
+  )
+{
+  UINT32           FspMeasureMask;
+  FSP_INFO_HEADER  *FspHeaderPtr;
+
+  FspMeasureMask = PcdGet32 (PcdFspMeasurementConfig);
+  if ((FspMeasureMask & FSP_MEASURE_FSPUPD) != 0) {
+    FspHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader (FirmwareBlobBase);
+    if (FspHeaderPtr != NULL) {
+      return MeasureFspFirmwareBlobWithCfg (
+               Description,
+               FirmwareBlobBase,
+               FirmwareBlobLength,
+               FspHeaderPtr->CfgRegionOffset,
+               FspHeaderPtr->CfgRegionSize
+               );
+    }
+  }
+
+  return MeasureFirmwareBlob (PcrIndex, Description, FirmwareBlobBase, FirmwareBlobLength);
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
new file mode 100644
index 0000000000..6f02c0113b
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
@@ -0,0 +1,66 @@
+## @file
+#  Provide FSP API related function.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseFspWrapperApiLib
+  FILE_GUID                      = F42C789F-4D66-49AF-8C73-1AADC00437AC
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FspWrapperApiLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+  FspWrapperApiLib.c
+
+[Sources.IA32]
+  IA32/DispatchExecute.c
+
+[Sources.X64]
+  X64/DispatchExecute.c
+  X64/Thunk64To32.nasm
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+[Guids]
+  gFspHeaderFileGuid            ## CONSUMES ## GUID
+
+[Pcd]
+  gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInMemory ## CONSUMES
+  gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInMemory ## CONSUMES
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c
new file mode 100644
index 0000000000..80d64f9bd2
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/FspWrapperApiLib.c
@@ -0,0 +1,235 @@
+/** @file
+  Provide FSP API related function.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/FspWrapperApiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+/**
+  Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
+  long mode.
+
+  @param[in] Function     The 32bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 32bit code.
+  @param[in] Param2       The second parameter to pass to 32bit code.
+
+  @return EFI_STATUS.
+**/
+EFI_STATUS
+Execute32BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  );
+
+/**
+  Wrapper to execute 64-bit code directly from long mode.
+
+  @param[in] Function     The 64bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 64bit code.
+  @param[in] Param2       The second parameter to pass to 64bit code.
+
+  @return EFI_STATUS.
+**/
+EFI_STATUS
+Execute64BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  );
+
+/**
+  Find FSP header pointer.
+
+  @param[in] FlashFvFspBase Flash address of FSP FV.
+
+  @return FSP header pointer.
+**/
+FSP_INFO_HEADER *
+EFIAPI
+FspFindFspHeader (
+  IN EFI_PHYSICAL_ADDRESS  FlashFvFspBase
+  )
+{
+  UINT8  *CheckPointer;
+
+  CheckPointer = (UINT8 *)(UINTN)FlashFvFspBase;
+
+  if (((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->Signature != EFI_FVH_SIGNATURE) {
+    return NULL;
+  }
+
+  if (((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->ExtHeaderOffset != 0) {
+    CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->ExtHeaderOffset;
+    CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_EXT_HEADER *)CheckPointer)->ExtHeaderSize;
+    CheckPointer = (UINT8 *)ALIGN_POINTER (CheckPointer, 8);
+  } else {
+    CheckPointer = CheckPointer + ((EFI_FIRMWARE_VOLUME_HEADER *)CheckPointer)->HeaderLength;
+  }
+
+  CheckPointer = CheckPointer + sizeof (EFI_FFS_FILE_HEADER);
+
+  if (((EFI_RAW_SECTION *)CheckPointer)->Type != EFI_SECTION_RAW) {
+    return NULL;
+  }
+
+  CheckPointer = CheckPointer + sizeof (EFI_RAW_SECTION);
+
+  return (FSP_INFO_HEADER *)CheckPointer;
+}
+
+/**
+  Call FSP API - FspNotifyPhase.
+
+  @param[in] NotifyPhaseParams Address pointer to the NOTIFY_PHASE_PARAMS structure.
+
+  @return EFI status returned by FspNotifyPhase API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspNotifyPhase (
+  IN NOTIFY_PHASE_PARAMS  *NotifyPhaseParams
+  )
+{
+  FSP_INFO_HEADER   *FspHeader;
+  FSP_NOTIFY_PHASE  NotifyPhaseApi;
+  EFI_STATUS        Status;
+  BOOLEAN           InterruptState;
+
+  FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddressInMemory));
+  if (FspHeader == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  NotifyPhaseApi = (FSP_NOTIFY_PHASE)((UINTN)FspHeader->ImageBase + FspHeader->NotifyPhaseEntryOffset);
+  InterruptState = SaveAndDisableInterrupts ();
+  DEBUG ((DEBUG_ERROR, "Before FSP interrupt status:%llx\n", (UINT64)InterruptState));
+  if ((FspHeader->ImageAttribute & IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT) == FSP_IA32) {
+    Status = Execute32BitCode ((UINTN)NotifyPhaseApi, (UINTN)NotifyPhaseParams, (UINTN)NULL);
+  } else {
+    Status = Execute64BitCode ((UINTN)NotifyPhaseApi, (UINTN)NotifyPhaseParams, (UINTN)NULL);
+  }
+
+  SetInterruptState (InterruptState);
+
+  return Status;
+}
+
+/**
+  Call FSP API - FspMemoryInit.
+
+  @param[in]  FspmUpdDataPtr Address pointer to the FSP_MEMORY_INIT_PARAMS structure.
+  @param[out] HobListPtr     Address of the HobList pointer.
+
+  @return EFI status returned by FspMemoryInit API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspMemoryInit (
+  IN VOID   *FspmUpdDataPtr,
+  OUT VOID  **HobListPtr
+  )
+{
+  FSP_INFO_HEADER  *FspHeader;
+  FSP_MEMORY_INIT  FspMemoryInitApi;
+  EFI_STATUS       Status;
+  BOOLEAN          InterruptState;
+
+  FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddressInMemory));
+  if (FspHeader == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  FspMemoryInitApi = (FSP_MEMORY_INIT)((UINTN)FspHeader->ImageBase + FspHeader->FspMemoryInitEntryOffset);
+  InterruptState   = SaveAndDisableInterrupts ();
+  if ((FspHeader->ImageAttribute & IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT) == FSP_IA32) {
+    Status = Execute32BitCode ((UINTN)FspMemoryInitApi, (UINTN)FspmUpdDataPtr, (UINTN)HobListPtr);
+  } else {
+    Status = Execute64BitCode ((UINTN)FspMemoryInitApi, (UINTN)FspmUpdDataPtr, (UINTN)HobListPtr);
+  }
+
+  SetInterruptState (InterruptState);
+
+  return Status;
+}
+
+/**
+  Call FSP API - TempRamExit.
+
+  @param[in] TempRamExitParam    Address pointer to the TempRamExit parameters structure.
+
+  @return EFI status returned by TempRamExit API.
+**/
+EFI_STATUS
+EFIAPI
+CallTempRamExit (
+  IN VOID  *TempRamExitParam
+  )
+{
+  FSP_INFO_HEADER    *FspHeader;
+  FSP_TEMP_RAM_EXIT  TempRamExitApi;
+  EFI_STATUS         Status;
+  BOOLEAN            InterruptState;
+
+  FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddressInMemory));
+  if (FspHeader == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  TempRamExitApi = (FSP_TEMP_RAM_EXIT)((UINTN)FspHeader->ImageBase + FspHeader->TempRamExitEntryOffset);
+  InterruptState = SaveAndDisableInterrupts ();
+  if ((FspHeader->ImageAttribute & IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT) == FSP_IA32) {
+    Status = Execute32BitCode ((UINTN)TempRamExitApi, (UINTN)TempRamExitParam, (UINTN)NULL);
+  } else {
+    Status = Execute64BitCode ((UINTN)TempRamExitApi, (UINTN)TempRamExitParam, (UINTN)NULL);
+  }
+
+  SetInterruptState (InterruptState);
+
+  return Status;
+}
+
+/**
+  Call FSP API - FspSiliconInit.
+
+  @param[in] FspsUpdDataPtr Address pointer to the Silicon Init parameters structure.
+
+  @return EFI status returned by FspSiliconInit API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspSiliconInit (
+  IN VOID  *FspsUpdDataPtr
+  )
+{
+  FSP_INFO_HEADER   *FspHeader;
+  FSP_SILICON_INIT  FspSiliconInitApi;
+  EFI_STATUS        Status;
+  BOOLEAN           InterruptState;
+
+  FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddressInMemory));
+  if (FspHeader == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  FspSiliconInitApi = (FSP_SILICON_INIT)((UINTN)FspHeader->ImageBase + FspHeader->FspSiliconInitEntryOffset);
+  InterruptState    = SaveAndDisableInterrupts ();
+  if ((FspHeader->ImageAttribute & IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT) == FSP_IA32) {
+    Status = Execute32BitCode ((UINTN)FspSiliconInitApi, (UINTN)FspsUpdDataPtr, (UINTN)NULL);
+  } else {
+    Status = Execute64BitCode ((UINTN)FspSiliconInitApi, (UINTN)FspsUpdDataPtr, (UINTN)NULL);
+  }
+
+  SetInterruptState (InterruptState);
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c
new file mode 100644
index 0000000000..434eb549a4
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/IA32/DispatchExecute.c
@@ -0,0 +1,71 @@
+/** @file
+  Execute 32-bit code in Protected Mode.
+
+  Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <FspEas.h>
+
+/**
+  FSP API functions.
+
+  @param[in] Param1       The first parameter to pass to 32bit code.
+  @param[in] Param2       The second parameter to pass to 32bit code.
+
+  @return EFI_STATUS.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_FUNCTION)(
+  IN VOID *Param1,
+  IN VOID *Param2
+  );
+
+/**
+  Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
+  long mode.
+
+  @param[in] Function     The 32bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 32bit code.
+  @param[in] Param2       The second parameter to pass to 32bit code.
+
+  @return EFI_STATUS.
+**/
+EFI_STATUS
+Execute32BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  )
+{
+  FSP_FUNCTION  EntryFunc;
+  EFI_STATUS    Status;
+
+  EntryFunc = (FSP_FUNCTION)(UINTN)(Function);
+  Status    = EntryFunc ((VOID *)(UINTN)Param1, (VOID *)(UINTN)Param2);
+
+  return Status;
+}
+
+/**
+  Wrapper for a thunk to transition from compatibility mode to long mode to execute 64-bit code and then transit back to
+  compatibility mode.
+
+  @param[in] Function     The 64bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 64bit code.
+  @param[in] Param2       The second parameter to pass to 64bit code.
+
+  @return EFI_STATUS.
+**/
+EFI_STATUS
+Execute64BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c
new file mode 100644
index 0000000000..3c34806286
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/DispatchExecute.c
@@ -0,0 +1,167 @@
+/** @file
+  Execute 64-bit code in Long Mode.
+  Provide a thunk function to transition from long mode to compatibility mode to execute 32-bit code and then transit
+  back to long mode.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <FspEas.h>
+#include <Library/DebugLib.h>
+
+UINT64
+ReadRsp (
+  VOID
+  );
+
+/**
+  FSP API functions.
+
+  @param[in] Param1       The first parameter to pass to 64bit code.
+  @param[in] Param2       The second parameter to pass to 64bit code.
+
+  @return EFI_STATUS.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_FUNCTION)(
+  IN VOID *Param1,
+  IN VOID *Param2
+  );
+
+#pragma pack(1)
+typedef union {
+  struct {
+    UINT32    LimitLow    : 16;
+    UINT32    BaseLow     : 16;
+    UINT32    BaseMid     : 8;
+    UINT32    Type        : 4;
+    UINT32    System      : 1;
+    UINT32    Dpl         : 2;
+    UINT32    Present     : 1;
+    UINT32    LimitHigh   : 4;
+    UINT32    Software    : 1;
+    UINT32    Reserved    : 1;
+    UINT32    DefaultSize : 1;
+    UINT32    Granularity : 1;
+    UINT32    BaseHigh    : 8;
+  } Bits;
+  UINT64    Uint64;
+} IA32_GDT;
+#pragma pack()
+
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT  mGdtEntries[] = {
+  {
+    { 0,      0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0, 0 }
+  },                                                            /* 0x0:  reserve */
+  {
+    { 0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0 }
+  },                                                            /* 0x8:  compatibility mode */
+  {
+    { 0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0 }
+  },                                                            /* 0x10: for long mode */
+  {
+    { 0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0 }
+  },                                                            /* 0x18: data */
+  {
+    { 0,      0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0, 0 }
+  },                                                            /* 0x20: reserve */
+};
+
+//
+// IA32 Gdt register
+//
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR  mGdt = {
+  sizeof (mGdtEntries) - 1,
+  (UINTN)mGdtEntries
+};
+
+/**
+  Assembly function to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
+  long mode.
+
+  @param[in] Function     The 32bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 32bit code
+  @param[in] Param2       The second parameter to pass to 32bit code
+  @param[in] InternalGdtr The GDT and GDT descriptor used by this library
+
+  @return status.
+**/
+UINT32
+EFIAPI
+AsmExecute32BitCode (
+  IN UINT64           Function,
+  IN UINT64           Param1,
+  IN UINT64           Param2,
+  IN IA32_DESCRIPTOR  *InternalGdtr
+  );
+
+/**
+  Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
+  long mode.
+
+  @param[in] Function     The 32bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 32bit code.
+  @param[in] Param2       The second parameter to pass to 32bit code.
+
+  @return EFI_STATUS.
+**/
+IA32_DESCRIPTOR  MemoryIdtr;
+EFI_STATUS
+Execute32BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  )
+{
+  EFI_STATUS       Status;
+  IA32_DESCRIPTOR  Idtr;
+
+  // Idtr might be changed inside of FSP. 32bit FSP only knows the <4G address.
+  // If IDTR.Base is >4G, FSP can not handle. So we need save/restore IDTR here for X64 only.
+  // Interrupt is already disabled here, so it is safety to update IDTR.
+  //
+  AsmReadIdtr (&Idtr);
+  MemoryIdtr = Idtr;
+  DEBUG ((DEBUG_ERROR, "Before FSP:%llx\n", ReadRsp ()));
+  Status = AsmExecute32BitCode (Function, Param1, Param2, &mGdt);
+  DEBUG ((DEBUG_ERROR, "After FSP:%llx\n", ReadRsp ()));
+  ASSERT (Idtr.Limit == MemoryIdtr.Limit && Idtr.Base == MemoryIdtr.Base);
+  //
+  // Convert FSP Status code from 32bit to 64bit to match caller expectation.
+  //
+  Status = (Status & ~(BIT31 + BIT30)) | LShiftU64 (Status & (BIT31 + BIT30), 32);
+  AsmWriteIdtr (&Idtr);
+
+  return Status;
+}
+
+/**
+  Wrapper to execute 64-bit code directly from long mode.
+
+  @param[in] Function     The 64bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 64bit code.
+  @param[in] Param2       The second parameter to pass to 64bit code.
+
+  @return EFI_STATUS.
+**/
+EFI_STATUS
+Execute64BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  )
+{
+  FSP_FUNCTION  EntryFunc;
+  EFI_STATUS    Status;
+
+  EntryFunc = (FSP_FUNCTION)(UINTN)(Function);
+  Status    = EntryFunc ((VOID *)(UINTN)Param1, (VOID *)(UINTN)Param2);
+
+  return Status;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm
new file mode 100644
index 0000000000..f1a14b2446
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/X64/Thunk64To32.nasm
@@ -0,0 +1,252 @@
+;/** @file
+;   This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then
+;   transit back to long mode.
+;
+; Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;
+; Module Name:
+;
+;    Thunk64To32.nasm
+;
+; Abstract:
+;
+;   This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then
+;   transit back to long mode.
+;
+;-------------------------------------------------------------------------------
+    DEFAULT REL
+    SECTION .text
+;----------------------------------------------------------------------------
+; Procedure:    AsmExecute32BitCode
+;
+; Input:        None
+;
+; Output:       None
+;
+; Prototype:    UINT32
+;               AsmExecute32BitCode (
+;                 IN UINT64           Function,
+;                 IN UINT64           Param1,
+;                 IN UINT64           Param2,
+;                 IN IA32_DESCRIPTOR  *InternalGdtr
+;                 );
+;
+;
+; Description:  A thunk function to execute 32-bit code in long mode.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(AsmExecute32BitCode)
+ASM_PFX(AsmExecute32BitCode):
+    ;
+    ; save IFLAG and disable it
+    ;
+    pushfq
+    cli
+
+    ;
+    ; save original GDTR and CS
+    ;
+    mov     rax, ds
+    push    rax
+    mov     rax, cs
+    push    rax
+    sub     rsp, 0x10
+    sgdt    [rsp]
+    ;
+    ; load internal GDT
+    ;
+    lgdt    [r9]
+    ;
+    ; Save general purpose register and rflag register
+    ;
+    pushfq
+    ; push AMD64-specific r8~r15.
+    push    r8
+    push    r9
+    push    r10
+    push    r11
+    push    r12
+    push    r13
+    push    r14
+    push    r15
+
+    push    rdi
+    push    rsi
+    push    rbp
+    push    rbx
+
+    ;
+    ; save CR3
+    ;
+    mov     rax, cr3
+    mov     rbp, rax
+
+    ;
+    ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode
+    ;
+    mov     rax, dword 0x10              ; load long mode selector
+    shl     rax, 32
+    lea     r9,  [ReloadCS]          ;Assume the ReloadCS is under 4G
+    or      rax, r9
+    push    rax
+    ;
+    ; Save parameters for 32-bit function call
+    ;
+    mov     rax, r8
+    shl     rax, 32
+    or      rax, rdx
+    push    rax
+    ;
+    ; save the 32-bit function entry and the return address into stack which will be
+    ; retrieve in compatibility mode.
+    ;
+    lea     rax, [ReturnBack]   ;Assume the ReloadCS is under 4G
+    shl     rax, 32
+    or      rax, rcx
+    push    rax
+
+    ;
+    ; let rax save DS
+    ;
+    mov     rax, dword 0x18
+
+    ;
+    ; Change to Compatible Segment
+    ;
+    mov     rcx, dword 0x8               ; load compatible mode selector
+    shl     rcx, 32
+    lea     rdx, [Compatible] ; assume address < 4G
+    or      rcx, rdx
+    push    rcx
+    retf
+
+Compatible:
+    ; reload DS/ES/SS to make sure they are correct referred to current GDT
+    mov     ds, ax
+    mov     es, ax
+    mov     ss, ax
+
+    ;
+    ; Disable paging
+    ;
+    mov     rcx, cr0
+    btc     ecx, 31
+    mov     cr0, rcx
+    ;
+    ; Clear EFER.LME
+    ;
+    mov     ecx, 0xC0000080
+    rdmsr
+    btc     eax, 8
+    wrmsr
+
+; Now we are in protected mode
+    ;
+    ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G
+    ;
+    pop    rax                 ; Here is the function entry
+    ;
+    ; Now the parameter is at the bottom of the stack,  then call in to IA32 function.
+    ;
+    jmp   rax
+ReturnBack:
+    mov   ebx, eax             ; save return status
+    pop   rcx                  ; drop param1
+    pop   rcx                  ; drop param2
+
+    ;
+    ; restore CR4
+    ;
+    mov     rax, cr4
+    bts     eax, 5
+    mov     cr4, rax
+
+    ;
+    ; restore CR3
+    ;
+    mov     eax, ebp
+    mov     cr3, rax
+
+    ;
+    ; Set EFER.LME to re-enable ia32-e
+    ;
+    mov     ecx, 0xC0000080
+    rdmsr
+    bts     eax, 8
+    wrmsr
+    ;
+    ; Enable paging
+    ;
+    mov     rax, cr0
+    bts     eax, 31
+    mov     cr0, rax
+; Now we are in compatible mode
+
+    ;
+    ; Reload cs register
+    ;
+    retf
+ReloadCS:
+    ;
+    ; Now we're in Long Mode
+    ;
+    ;
+    ; Restore C register and eax hold the return status from 32-bit function.
+    ; Note: Do not touch rax from now which hold the return value from IA32 function
+    ;
+    mov     eax, ebx ; put return status to EAX
+    pop     rbx
+    pop     rbp
+    pop     rsi
+    pop     rdi
+    ; pop AMD64-specific r8~r15
+    pop     r15
+    pop     r14
+    pop     r13
+    pop     r12
+    pop     r11
+    pop     r10
+    pop     r9
+    pop     r8
+
+    popfq
+    ;
+    ; Switch to original GDT and CS. here rsp is pointer to the original GDT descriptor.
+    ;
+    lgdt    [rsp]
+    ;
+    ; drop GDT descriptor in stack
+    ;
+    add     rsp, 0x10
+    ;
+    ; switch to original CS and GDTR
+    ;
+    pop     r9                 ; get  CS
+    shl     r9,  32            ; rcx[32..47] <- Cs
+    lea     rcx, [.0]
+    or      rcx, r9
+    push    rcx
+    retf
+.0:
+    ;
+    ; Reload original DS/ES/SS
+    ;
+    pop     rcx
+    mov     ds, rcx
+    mov     es, rcx
+    mov     ss, rcx
+
+    ;
+    ; Restore IFLAG
+    ;
+    popfq
+
+    ret
+
+global ASM_PFX(ReadRsp)
+ASM_PFX(ReadRsp):
+    mov rax,rsp
+    ret
\ No newline at end of file
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
new file mode 100644
index 0000000000..6b94a67905
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
@@ -0,0 +1,49 @@
+### @file
+#  Provide FSP wrapper API test related function.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (C) 2016, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = BaseFspWrapperApiTestLibNull
+  FILE_GUID                      = E7E96F88-017B-417C-8DC8-B84C2B877020
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = PEIM
+  LIBRARY_CLASS                  = FspWrapperApiTestLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+  FspWrapperApiTestNull.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+
+[LibraryClasses]
+  DebugLib
+
+[Guids]
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
new file mode 100644
index 0000000000..19bd3afc29
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
@@ -0,0 +1,60 @@
+/** @file
+  Provide FSP wrapper API test related function.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+/**
+  Test the output of FSP API - FspMemoryInit.
+
+  @param[in]  FspmUpdDataPtr Address pointer to the FSP_MEMORY_INIT_PARAMS structure.
+  @param[in]  HobListPtr     Address of the HobList pointer.
+
+  @return test result on output of FspMemoryInit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspMemoryInitApiOutput (
+  IN  VOID  *FspmUpdDataPtr,
+  IN  VOID  **HobListPtr
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Test the output of FSP API - TempRamExit.
+
+  @param[in] TempRamExitParam    Address pointer to the TempRamExit parameters structure.
+
+  @return test result on output of TempRamExit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspTempRamExitApiOutput (
+  IN VOID  *TempRamExitParam
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Test the output of FSP API - FspSiliconInit.
+
+  @param[in] FspsUpdDataPtr Address pointer to the Silicon Init parameters structure.
+
+  @return test result on output of FspSiliconInit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspSiliconInitApiOutput (
+  IN  VOID  *FspsUpdDataPtr
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
new file mode 100644
index 0000000000..1b0e9ed1c8
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
@@ -0,0 +1,72 @@
+## @file
+#  Sample to provide FSP wrapper platform related function.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseFspWrapperPlatformLibSample
+  FILE_GUID                      = 12F38E73-B34D-4559-99E5-AE2DCD002156
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FspWrapperPlatformLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+  FspWrapperPlatformLibSample.c
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+
+[Packages]
+  MdePkg/MdePkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[Ppis]
+  gEfiPeiSmbus2PpiGuid
+
+[LibraryClasses]
+  AmdIdsHookExtLib
+
+[Guids]
+  gEfiSmmPeiSmramMemoryReserveGuid
+  gEfiAcpiVariableGuid
+  gAmdResourceSizeForEachRbGuid
+  gAmdTotalNumberOfRootBridgesGuid
+  gAmdPbsSystemConfigurationGuid
+  gApSyncFlagNvVariableGuid
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress     # CONSUMES
+  gFsp2WrapperTokenSpaceGuid.PcdFspoDxeBaseAddressInMemory
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
new file mode 100644
index 0000000000..1afcf68f85
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
@@ -0,0 +1,347 @@
+/** @file
+  Sample to provide FSP wrapper related function.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/PcdLib.h>
+#include <FspEas/FspApi.h>
+#include <FspmUpd.h>
+#include <FspsUpd.h>
+#include <Library/HobLib.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Ppi/Smbus2.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Library/PeiServicesLib.h>
+#include <Guid/AcpiS3Context.h>
+
+#pragma pack(push, 1)
+typedef struct {
+  UINT8    connector_type;
+  UINT8    aux_index;
+  UINT8    hdp_index;
+  UINT8    reserved;
+} fsp_ddi_descriptor;
+#pragma pack(pop)
+
+extern EFI_GUID  gEfiSmmPeiSmramMemoryReserveGuid;
+
+extern EFI_GUID  gAmdResourceSizeForEachRbGuid;
+extern EFI_GUID  gAmdTotalNumberOfRootBridgesGuid;
+extern EFI_GUID  gAmdPbsSystemConfigurationGuid;
+extern EFI_GUID  gApSyncFlagNvVariableGuid;
+
+typedef enum {
+  IDS_HOOK_SUCCESS = 0,         ///< The service completed normally
+  IDS_HOOK_UNSUPPORTED,         ///< Unsupported IDS HOOK
+  IDS_HOOK_BUFFER_TOO_SMALL,    ///< Too small buffer
+  IDS_HOOK_NOT_FOUND,           ///< Haven't found accordingly service entry for specific IDS HOOK ID
+  IDS_HOOK_ERROR,               ///< Error happens during service IDS HOOK
+  IDS_HOOK_SKIP,                ///< Use to notify the IDS HOOK caller to skip a block of codes, used for IDS_HOOK_SKIP
+  IDS_HOOK_NO_SKIP,             ///< Use to notify the IDS HOOK caller not skip a block of codes, used for IDS_HOOK_SKIP
+  IDS_HOOK_MAX                  ///< Not a status, for limit checking.
+} IDS_HOOK_STATUS;
+
+IDS_HOOK_STATUS
+GetIdsNvTable (
+  IN OUT   VOID    *IdsNvTable,
+  IN OUT   UINT32  *IdsNvTableSize
+  );
+
+STATIC
+EFI_STATUS
+GetIdsNvData (
+  FSPM_UPD *volatile  FspmUpd
+  )
+{
+  VOID             *IdsNvTableData;
+  UINT32           IdsNvDataSize = 0;
+  IDS_HOOK_STATUS  Status        = GetIdsNvTable (NULL, &IdsNvDataSize);
+
+  if ((Status == IDS_HOOK_BUFFER_TOO_SMALL) || (Status == IDS_HOOK_SUCCESS)) {
+    // The CBS code doesn't follow its header!
+    IdsNvTableData = AllocatePool (IdsNvDataSize+100);
+    if (IdsNvTableData != NULL) {
+      Status = GetIdsNvTable (IdsNvTableData, &IdsNvDataSize);
+      if (Status == IDS_HOOK_SUCCESS) {
+        FspmUpd->FspmConfig.ids_nv_table_address = (UINT32)(UINTN)IdsNvTableData;
+        FspmUpd->FspmConfig.ids_nv_table_size    = IdsNvDataSize;
+        DEBUG ((
+          DEBUG_INFO,
+          "IDS NV Table address:%x, size:%x\n", \
+          FspmUpd->FspmConfig.ids_nv_table_address,
+          FspmUpd->FspmConfig.ids_nv_table_size
+          ));
+        return EFI_SUCCESS;
+      } else {
+        DEBUG ((DEBUG_ERROR, "Get NV Table #3:%d\n", Status));
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "Get NV Table #2:%d\n", Status));
+    }
+  } else {
+    DEBUG ((DEBUG_ERROR, "Get NV Table #1:%d\n", Status));
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  This function overrides the default configurations in the FSP-S UPD data region.
+
+  @param[in,out] FspUpdRgnPtr   A pointer to the UPD data region data structure.
+
+**/
+VOID
+EFIAPI
+UpdateFspsUpdData (
+  IN OUT VOID  *FspUpdRgnPtr
+  )
+{
+  EFI_SMRAM_HOB_DESCRIPTOR_BLOCK  *SmramHob = GetFirstGuidHob (
+                                                &gEfiSmmPeiSmramMemoryReserveGuid
+                                                );
+
+  if (SmramHob != NULL) {
+    ((FSPS_UPD *)FspUpdRgnPtr)->FspsConfig.smram_hob_base_addr = (UINT32)(UINTN)GET_GUID_HOB_DATA (SmramHob);
+    ((FSPS_UPD *)FspUpdRgnPtr)->FspsConfig.smram_hob_size      =      (UINT32)GET_GUID_HOB_DATA_SIZE (SmramHob);
+  }
+
+  EFI_SMRAM_DESCRIPTOR  *SmramDescriptor = GetFirstGuidHob (&gEfiAcpiVariableGuid);
+
+  if (SmramDescriptor != NULL) {
+    ((FSPS_UPD *)FspUpdRgnPtr)->FspsConfig.smram_hob_descriptor_base_addr = (UINT32)(UINTN)GET_GUID_HOB_DATA (SmramDescriptor);
+    ((FSPS_UPD *)FspUpdRgnPtr)->FspsConfig.smram_hob_descriptor_size      =      (UINT32)GET_GUID_HOB_DATA_SIZE (SmramDescriptor);
+  } else {
+    DEBUG ((DEBUG_ERROR, "Cannot found SmramDescriptor!\n"));
+  }
+
+  ((FSPS_UPD *)FspUpdRgnPtr)->FspsConfig.fsp_o_dxe_volume_address = PcdGet32 (PcdFspoDxeBaseAddressInMemory);
+  ((FSPS_UPD *)FspUpdRgnPtr)->FspsConfig.page_address_below_1mb   = 0x10000;
+}
+
+/**
+  This function overrides the default configurations in the FSP-M UPD data region.
+
+  @note At this point, memory is NOT ready, PeiServices are available to use.
+
+  @param[in,out] FspUpdRgnPtr   A pointer to the UPD data region data structure.
+
+**/
+VOID
+EFIAPI
+UpdateFspmUpdDataForFabric (
+  IN OUT VOID  *FspUpdRgnPtr
+  )
+{
+  DEBUG ((DEBUG_INFO, "%a Enter\n", __FUNCTION__));
+  FSPM_UPD                         *Upd           = (FSPM_UPD *)FspUpdRgnPtr;
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *ReadVariable2 = NULL;
+  EFI_STATUS                       Status         = PeiServicesLocatePpi (&gEfiPeiReadOnlyVariable2PpiGuid, 0, NULL, (VOID **)&ReadVariable2);
+
+  ASSERT (Status == EFI_SUCCESS);
+  UINT32  VariableSize = 0;
+  VOID    *Buffer      = NULL;
+
+  Status = ReadVariable2->GetVariable (
+                            ReadVariable2,
+                            L"ResourceSizeForEachRb",
+                            &gAmdResourceSizeForEachRbGuid,
+                            NULL,
+                            &VariableSize,
+                            NULL
+                            );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Buffer = AllocatePool (VariableSize);
+    ASSERT (Buffer != NULL);
+    Status = ReadVariable2->GetVariable (
+                              ReadVariable2,
+                              L"ResourceSizeForEachRb",
+                              &gAmdResourceSizeForEachRbGuid,
+                              NULL,
+                              &VariableSize,
+                              Buffer
+                              );
+    if (!EFI_ERROR (Status)) {
+      Upd->FspmConfig.resource_size_for_each_rb_ptr  = (UINT32)(UINTN)Buffer;
+      Upd->FspmConfig.resource_size_for_each_rb_size = VariableSize;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "Get variable %s returns %r\n", L"ResourceSizeForEachRb", Status));
+  VariableSize = 0;
+  Buffer       = NULL;
+  Status       = ReadVariable2->GetVariable (
+                                  ReadVariable2,
+                                  L"TotalNumberOfRootBridges",
+                                  &gAmdTotalNumberOfRootBridgesGuid,
+                                  NULL,
+                                  &VariableSize,
+                                  NULL
+                                  );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Buffer = AllocatePool (VariableSize);
+    ASSERT (Buffer != NULL);
+    Status = ReadVariable2->GetVariable (
+                              ReadVariable2,
+                              L"TotalNumberOfRootBridges",
+                              &gAmdTotalNumberOfRootBridgesGuid,
+                              NULL,
+                              &VariableSize,
+                              Buffer
+                              );
+    if (!EFI_ERROR (Status)) {
+      Upd->FspmConfig.total_number_of_root_bridges_ptr  = (UINT32)(UINTN)Buffer;
+      Upd->FspmConfig.total_number_of_root_bridges_size = VariableSize;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "Get variable %s returns %r\n", L"TotalNumberOfRootBridges", Status));
+  VariableSize = 0;
+  Buffer       = NULL;
+  Status       = ReadVariable2->GetVariable (
+                                  ReadVariable2,
+                                  L"AMD_PBS_SETUP",
+                                  &gAmdPbsSystemConfigurationGuid,
+                                  NULL,
+                                  &VariableSize,
+                                  NULL
+                                  );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Buffer = AllocatePool (VariableSize);
+    ASSERT (Buffer != NULL);
+    Status = ReadVariable2->GetVariable (
+                              ReadVariable2,
+                              L"AMD_PBS_SETUP",
+                              &gAmdPbsSystemConfigurationGuid,
+                              NULL,
+                              &VariableSize,
+                              Buffer
+                              );
+    if (!EFI_ERROR (Status)) {
+      Upd->FspmConfig.amd_pbs_setup_ptr  = (UINT32)(UINTN)Buffer;
+      Upd->FspmConfig.amd_pbs_setup_size = VariableSize;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "Get variable %s returns %r\n", L"AMD_PBS_SETUP", Status));
+  VariableSize = 0;
+  Buffer       = NULL;
+  Status       = ReadVariable2->GetVariable (
+                                  ReadVariable2,
+                                  L"ApSyncFlagNv",
+                                  &gApSyncFlagNvVariableGuid,
+                                  NULL,
+                                  &VariableSize,
+                                  NULL
+                                  );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Buffer = AllocatePool (VariableSize);
+    ASSERT (Buffer != NULL);
+    Status = ReadVariable2->GetVariable (
+                              ReadVariable2,
+                              L"ApSyncFlagNv",
+                              &gApSyncFlagNvVariableGuid,
+                              NULL,
+                              &VariableSize,
+                              Buffer
+                              );
+    if (!EFI_ERROR (Status)) {
+      Upd->FspmConfig.ap_sync_flag_nv_ptr  = (UINT32)(UINTN)Buffer;
+      Upd->FspmConfig.ap_sync_flag_nv_size = VariableSize;
+    }
+
+    DEBUG ((DEBUG_INFO, "Get variable %s returns %r\n", L"ApSyncFlagNv", Status));
+  }
+}
+
+/**
+  This function overrides the default configurations in the FSP-M UPD data region.
+
+  @note At this point, memory is NOT ready, PeiServices are available to use.
+
+  @param[in,out] FspUpdRgnPtr   A pointer to the UPD data region data structure.
+
+**/
+VOID
+EFIAPI
+UpdateFspmUpdData (
+  IN OUT VOID  *FspUpdRgnPtr
+  )
+{
+  FSPM_UPD  *FspmUpd;
+
+  FspmUpd = (FSPM_UPD *)FspUpdRgnPtr;
+  EFI_BOOT_MODE  BootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+  PeiServicesGetBootMode (&BootMode);
+  FspmUpd->FspmArchUpd.BootMode  = BootMode;
+  FspmUpd->FspmArchUpd.StackBase = (VOID *)0x11000; // 1 Page for CPU reset in DXE.
+  FspmUpd->FspmArchUpd.StackSize = 0x20000;
+  DEBUG ((DEBUG_INFO, "Getting IDS NV Table returns status %r\n", GetIdsNvData (FspmUpd)));
+  UpdateFspmUpdDataForFabric (FspUpdRgnPtr);
+}
+
+/**
+  Update TempRamExit parameter.
+
+  @note At this point, memory is ready, PeiServices are available to use.
+
+  @return TempRamExit parameter.
+**/
+VOID *
+EFIAPI
+UpdateTempRamExitParam (
+  VOID
+  )
+{
+  return NULL;
+}
+
+/**
+  Get S3 PEI memory information.
+
+  @note At this point, memory is ready, and PeiServices are available to use.
+  Platform can get some data from SMRAM directly.
+
+  @param[out] S3PeiMemSize  PEI memory size to be installed in S3 phase.
+  @param[out] S3PeiMemBase  PEI memory base to be installed in S3 phase.
+
+  @return If S3 PEI memory information is got successfully.
+**/
+EFI_STATUS
+EFIAPI
+GetS3MemoryInfo (
+  OUT UINT64                *S3PeiMemSize,
+  OUT EFI_PHYSICAL_ADDRESS  *S3PeiMemBase
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Perform platform related reset in FSP wrapper.
+
+  This function will reset the system with requested ResetType.
+
+  @param[in] FspStatusResetType  The type of reset the platform has to perform.
+**/
+VOID
+EFIAPI
+CallFspWrapperResetSystem (
+  IN EFI_STATUS  FspStatusResetType
+  )
+{
+  //
+  // Perform reset according to the type.
+  //
+
+  CpuDeadLoop ();
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPhaseLibNull.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPhaseLibNull.inf
new file mode 100644
index 0000000000..6737705725
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPhaseLibNull.inf
@@ -0,0 +1,37 @@
+## @file
+#  FSP Wrapper to handle platform specific actions for
+#  FSP MultiPhase (SeparatePhase) Initialization.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BaseFspWrapperPlatformMultiPhaseLibNull
+  FILE_GUID                      = DB63E5AA-21C6-40BB-879A-CD1762C8427B
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FspWrapperPlatformMultiPhaseLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  FspWrapperPlatformMultiPhaseLibNull.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  BaseLib
+  PcdLib
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLibNull.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLibNull.c
new file mode 100644
index 0000000000..3a0d0e6088
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLibNull.c
@@ -0,0 +1,51 @@
+/** @file
+  FSP Wrapper to handle platform specific actions for
+  FSP MultiPhase (SeparatePhase) Initialization.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+/**
+  FSP Wrapper Platform MultiPhase Handler
+
+  @param[in] FspHobListPtr        - Pointer to FSP HobList (valid after FSP-M completed)
+  @param[in] ComponentIndex       - FSP Component which executing MultiPhase initialization.
+  @param[in] PhaseIndex           - Indicates current execution phase of FSP MultiPhase initialization.
+
+  @retval EFI_STATUS        Always return EFI_SUCCESS
+
+**/
+VOID
+EFIAPI
+FspWrapperPlatformMultiPhaseHandler (
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex,
+  IN UINT32    PhaseIndex
+  )
+{
+  /* Example platform actions as below
+  switch (ComponentIndex) {
+  case FspMultiPhaseMemInitApiIndex:
+    switch (PhaseIndex) {
+      case 1:
+        PlatformAction1 ();
+      break;
+    }
+    break;
+  case FspMultiPhaseSiInitApiIndex:
+    switch (PhaseIndex) {
+      case 1:
+        PlatformAction2 ();
+      break;
+    }
+    break;
+  }
+  */
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
new file mode 100644
index 0000000000..cfda44bc71
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
@@ -0,0 +1,531 @@
+/** @file
+  Support FSP Wrapper MultiPhase process.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <FspEas.h>
+#include <FspGlobalData.h>
+#include <Ppi/Variable.h>
+#include "../../Include/Library/FspWrapperPlatformMultiPhaseLib.h"
+#include <FspsUpd.h>
+#include <Protocol/SmbusHc.h>
+#include <Protocol/SmmAccess2.h>
+#include <Protocol/SmmControl2.h>
+#include <Protocol/Reset.h>
+#include <MultiPhaseSiPhases.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <FspExportedInterfaceHob.h>
+#include <Protocol/Smbios.h>
+#include <Pi/PiHob.h>
+
+extern EFI_GUID  gFspsUpdDataPointerAddressGuid;
+extern EFI_GUID  gEfiSmmBase2ProtocolGuid;
+extern EFI_GUID  gEfiSmmCommunicationProtocolGuid;
+extern EFI_GUID  gEfiMmCommunication2ProtocolGuid;
+extern EFI_GUID  gFchInitDonePolicyProtocolGuid;
+extern EFI_GUID  gEfiVariableArchProtocolGuid;
+extern EFI_GUID  gEfiSmmVariableProtocolGuid;
+extern EFI_GUID  gSmmVariableWriteGuid;
+extern EFI_GUID  gEfiHiiDatabaseProtocolGuid;
+extern EFI_GUID  gEfiHiiStringProtocolGuid;
+extern EFI_GUID  gEfiHiiConfigRoutingProtocolGuid;
+extern EFI_GUID  gPspFlashAccSmmCommReadyProtocolGuid;
+extern EFI_GUID  gFspSmmDependencyReadyProtocolGuid;
+extern EFI_GUID  gFspHobGuid;
+extern EFI_GUID  gFspExportedInterfaceHobGuid;
+
+STATIC FSPS_UPD *volatile  FspsUpd;
+static VOID                **mFspHobListPtr;
+
+// The EDK 202208 Doesn't hold these structs.
+typedef enum {
+  EnumMultiPhaseGetVariableRequestInfo  = 0x2,
+  EnumMultiPhaseCompleteVariableRequest = 0x3
+} FSP_MULTI_PHASE_ACTION_23;
+
+typedef enum {
+  FspMultiPhaseMemInitApiIndex = 8
+} FSP_API_INDEX_23;
+///
+/// Action definition for FspMultiPhaseSiInit API
+///
+typedef enum {
+  EnumFspVariableRequestGetVariable         = 0x0,
+  EnumFspVariableRequestGetNextVariableName = 0x1,
+  EnumFspVariableRequestSetVariable         = 0x2,
+  EnumFspVariableRequestQueryVariableInfo   = 0x3
+} FSP_VARIABLE_REQUEST_TYPE;
+
+#pragma pack(16)
+typedef struct {
+  IN     FSP_VARIABLE_REQUEST_TYPE    VariableRequest;
+  IN OUT CHAR16                       *VariableName;
+  IN OUT UINT64                       *VariableNameSize;
+  IN OUT EFI_GUID                     *VariableGuid;
+  IN OUT UINT32                       *Attributes;
+  IN OUT UINT64                       *DataSize;
+  IN OUT VOID                         *Data;
+  OUT    UINT64                       *MaximumVariableStorageSize;
+  OUT    UINT64                       *RemainingVariableStorageSize;
+  OUT    UINT64                       *MaximumVariableSize;
+} FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS;
+
+typedef struct {
+  EFI_STATUS    VariableRequestStatus;
+} FSP_MULTI_PHASE_COMPLETE_VARIABLE_REQUEST_PARAMS;
+
+#pragma pack()
+
+FSP_EXPORTED_INTERFACE_HOB  *ExportedInterfaceHob;
+
+EFI_STATUS
+EFIAPI
+CallFspMultiPhaseEntry (
+  IN VOID      *FspMultiPhaseParams,
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex
+  );
+
+/**
+  Execute 32-bit FSP API entry code.
+
+  @param[in] Function     The 32bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 32bit code.
+  @param[in] Param2       The second parameter to pass to 32bit code.
+
+  @return EFI_STATUS.
+**/
+EFI_STATUS
+Execute32BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  );
+
+/**
+  Execute 64-bit FSP API entry code.
+
+  @param[in] Function     The 64bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 64bit code.
+  @param[in] Param2       The second parameter to pass to 64bit code.
+
+  @return EFI_STATUS.
+**/
+EFI_STATUS
+Execute64BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  );
+
+/**
+  Call FspsMultiPhase API.
+
+  @param[in] FspsMultiPhaseParams - Parameters for MultiPhase API.
+  @param[in] FspHobListPtr        - Pointer to FSP HobList (valid after FSP-M completed)
+  @param[in] ComponentIndex       - FSP Component which executing MultiPhase initialization.
+
+  @return EFI_UNSUPPORTED  - the requested FspsMultiPhase API is not supported.
+  @return EFI_DEVICE_ERROR - the FSP header was not found.
+  @return EFI status returned by FspsMultiPhase API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspMultiPhaseEntry (
+  IN VOID      *FspMultiPhaseParams,
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex
+  )
+{
+  mFspHobListPtr = FspHobListPtr;
+  FSP_INFO_HEADER  *FspHeader;
+  //
+  // FSP_MULTI_PHASE_INIT and FSP_MULTI_PHASE_SI_INIT API functions having same prototype.
+  //
+  UINTN                   FspMultiPhaseApiEntry;
+  UINTN                   FspMultiPhaseApiOffset = 0;
+  EFI_STATUS              Status;
+  BOOLEAN                 InterruptState;
+  BOOLEAN                 IsVariableServiceRequest;
+  FSP_MULTI_PHASE_PARAMS  *FspMultiPhaseParamsPtr;
+
+  FspMultiPhaseParamsPtr   = (FSP_MULTI_PHASE_PARAMS *)FspMultiPhaseParams;
+  IsVariableServiceRequest = FALSE;
+  if ((FspMultiPhaseParamsPtr->MultiPhaseAction == (int)EnumMultiPhaseGetVariableRequestInfo) ||
+      (FspMultiPhaseParamsPtr->MultiPhaseAction == (int)EnumMultiPhaseCompleteVariableRequest))
+  {
+    IsVariableServiceRequest = TRUE;
+  }
+
+  if (ComponentIndex == FspMultiPhaseMemInitApiIndex) {
+    FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddressInMemory));
+    if (FspHeader == NULL) {
+      return EFI_DEVICE_ERROR;
+    } else if (FspHeader->SpecVersion < 0x24) {
+      return EFI_UNSUPPORTED;
+    }
+
+    FspMultiPhaseApiOffset = FspHeader->FspMultiPhaseMemInitEntryOffset;
+  } else if (ComponentIndex == FspMultiPhaseSiInitApiIndex) {
+    FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddressInMemory));
+    if (FspHeader == NULL) {
+      return EFI_DEVICE_ERROR;
+    } else if (FspHeader->SpecVersion < 0x22) {
+      return EFI_UNSUPPORTED;
+    } else if ((FspHeader->SpecVersion < 0x24) && (IsVariableServiceRequest == TRUE)) {
+      return EFI_UNSUPPORTED;
+    }
+
+    FspMultiPhaseApiOffset = FspHeader->FspMultiPhaseSiInitEntryOffset;
+  }
+
+  if (FspMultiPhaseApiOffset == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  FspMultiPhaseApiEntry = FspHeader->ImageBase + FspMultiPhaseApiOffset;
+  InterruptState        = SaveAndDisableInterrupts ();
+  if ((FspHeader->ImageAttribute & BIT2) == 0) {
+    // BIT2: IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT
+    Status = Execute32BitCode ((UINTN)FspMultiPhaseApiEntry, (UINTN)FspMultiPhaseParams, (UINTN)NULL);
+  } else {
+    Status = Execute64BitCode ((UINTN)FspMultiPhaseApiEntry, (UINTN)FspMultiPhaseParams, (UINTN)NULL);
+  }
+
+  SetInterruptState (InterruptState);
+
+  DEBUG ((DEBUG_ERROR, "CallFspMultiPhaseEntry return Status %r \n", Status));
+
+  return Status;
+}
+
+VOID
+EFIAPI
+OnRuntimeServiceReady (
+  EFI_EVENT  Event,
+  VOID       *Extra
+  )
+{
+  gBS->CloseEvent (Event);
+  DEBUG ((DEBUG_ERROR, "Runtime Service ready.\n"));
+  FSP_MULTI_PHASE_PARAMS  FspMultiPhaseParams;
+
+  FspMultiPhaseParams.MultiPhaseAction   = EnumMultiPhaseExecutePhase;
+  FspMultiPhaseParams.PhaseIndex         = EnumMultiPhaseAmdRuntimeServicesReadyPhase;
+  FspMultiPhaseParams.MultiPhaseParamPtr = NULL;
+ #if 1
+  ExportedInterfaceHob->GetVariable         = gST->RuntimeServices->GetVariable;
+  ExportedInterfaceHob->GetNextVariableName = gST->RuntimeServices->GetNextVariableName;
+  ExportedInterfaceHob->SetVariable         = gST->RuntimeServices->SetVariable;
+  ExportedInterfaceHob->QueryVariableInfo   = gST->RuntimeServices->QueryVariableInfo;
+  ASSERT (gST->RuntimeServices->GetVariable && gST->RuntimeServices->SetVariable);
+  VOID        *HiiProtocol;
+  EFI_STATUS  Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &HiiProtocol);
+  ASSERT (Status == EFI_SUCCESS);
+  ExportedInterfaceHob->HiiProtocol = HiiProtocol;
+  Status                            = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, &HiiProtocol);
+  ASSERT (Status == EFI_SUCCESS);
+  ExportedInterfaceHob->HiiStringProtocol = HiiProtocol;
+  Status                                  = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, &HiiProtocol);
+  ASSERT (Status == EFI_SUCCESS);
+  ExportedInterfaceHob->HiiConfigRoutingProtocol = HiiProtocol;
+ #endif
+  CallFspMultiPhaseEntry (&FspMultiPhaseParams, NULL, FspMultiPhaseSiInitApiIndex);
+}
+
+/**
+  FSP Wrapper MultiPhase Handler
+
+  @param[in, out] FspHobListPtr        - Pointer to FSP HobList (valid after FSP-M completed)
+  @param[in]      ComponentIndex       - FSP Component which executing MultiPhase initialization.
+
+  @retval EFI_UNSUPPORTED   Specific MultiPhase action was not supported.
+  @retval EFI_SUCCESS       MultiPhase action were completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+FspWrapperMultiPhaseHandler (
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex
+  )
+{
+  EFI_STATUS              Status;
+  FSP_MULTI_PHASE_PARAMS  FspMultiPhaseParams;
+  UINT32                  Index;
+  EFI_HANDLE              Handle      = NULL;
+  VOID                    *FspsUpdHob = GetFirstGuidHob (&gFspsUpdDataPointerAddressGuid);
+
+  if ( FspsUpdHob != NULL ) {
+    FspsUpd = ((FSPS_UPD *)(UINTN)(*(UINT32 *)GET_GUID_HOB_DATA (FspsUpdHob)));
+  }
+
+  FspsUpd->FspsConfig.nv_storage_variable_base    = PcdGet32 (PcdFlashNvStorageVariableBase);
+  FspsUpd->FspsConfig.nv_storage_variable_size    = PcdGet32 (PcdFlashNvStorageVariableSize);
+  FspsUpd->FspsConfig.nv_storage_ftw_working_base = PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
+  FspsUpd->FspsConfig.nv_storage_ftw_working_size = PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+  FspsUpd->FspsConfig.nv_storage_ftw_spare_base   = PcdGet32 (PcdFlashNvStorageFtwSpareBase);
+  FspsUpd->FspsConfig.nv_storage_ftw_spare_size   = PcdGet32 (PcdFlashNvStorageFtwSpareSize);
+
+  for (Index = 1; Index <= EnumMultiPhaseAmdCpmDxeTableReadyPhase; Index++) {
+    //
+    // Platform actions can be added in below function for each component and phase before returning control back to FSP.
+    //
+    FspWrapperPlatformMultiPhaseHandler (FspHobListPtr, ComponentIndex, Index);
+
+    FspMultiPhaseParams.MultiPhaseAction   = EnumMultiPhaseExecutePhase;
+    FspMultiPhaseParams.PhaseIndex         = Index;
+    FspMultiPhaseParams.MultiPhaseParamPtr = NULL;
+    Status                                 = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
+
+    //
+    // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+    //
+    if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+      DEBUG ((DEBUG_INFO, "FspMultiPhaseApi-0x%x requested reset %r\n", ComponentIndex, Status));
+      CallFspWrapperResetSystem ((UINTN)Status);
+    }
+
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  DEBUG ((DEBUG_ERROR, " FSP Multi Phase Silicon Phase #2 init done. Installing Protocol.\n"));
+  DEBUG ((DEBUG_ERROR, " *FspHobListPtr:%011p\n", *FspHobListPtr));
+  VOID  *ExportedInterfaceRawHob = GetNextGuidHob (&gFspExportedInterfaceHobGuid, *FspHobListPtr);
+
+  DEBUG ((DEBUG_ERROR, " ExportedInterfaceRawHob:%011p\n", ExportedInterfaceRawHob));
+  if ( ExportedInterfaceRawHob != NULL) {
+    ExportedInterfaceHob = GET_GUID_HOB_DATA (ExportedInterfaceRawHob);
+  } else {
+    DEBUG ((DEBUG_ERROR, " Cannot found Exported Interface HOB!\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  DEBUG ((DEBUG_ERROR, "ExportedInterfaceHob:%011p\n", ExportedInterfaceHob));
+  if ( FspsUpd != NULL ) {
+    DEBUG ((DEBUG_ERROR, "FSP-S UPD Ptr:%011p\n", FspsUpd));
+    // SMBUS Protocol
+    if (ExportedInterfaceHob->SmbusProtocol != 0) {
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &Handle,
+                      &gEfiSmbusHcProtocolGuid,
+                      ExportedInterfaceHob->SmbusProtocol,
+                      NULL
+                      );
+      Handle  = NULL;
+      Status |= gBS->InstallProtocolInterface (
+                       &Handle,
+                       &gFchInitDonePolicyProtocolGuid,
+                       EFI_NATIVE_INTERFACE,
+                       NULL
+                       );
+      if ( EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "Failed to install SMBUS Protocol!\n"));
+        return Status;
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "SMBUS operation address is 0!\n"));
+      return EFI_UNSUPPORTED;
+    }
+
+    // SMRAM Access 2 Protocol
+    if (ExportedInterfaceHob->SmmAccessProtocol != 0) {
+      Handle = NULL;
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &Handle,
+                      &gEfiSmmAccess2ProtocolGuid,
+                      ExportedInterfaceHob->SmmAccessProtocol,
+                      NULL
+                      );
+      if ( EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "Failed to install SMRAM Access Protocol!\n"));
+        return Status;
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "SMRAM access address is 0!\n"));
+      return EFI_UNSUPPORTED;
+    }
+
+    // SMRAM Control 2 Protocol
+    if (ExportedInterfaceHob->SmmControl2Protocol != 0) {
+      Handle = NULL;
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &Handle,
+                      &gEfiSmmControl2ProtocolGuid,
+                      ExportedInterfaceHob->SmmControl2Protocol,
+                      NULL
+                      );
+      if ( EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "Failed to install SMRAM Control Protocol!\n"));
+        return Status;
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "SMRAM control address is 0!\n"));
+      return EFI_UNSUPPORTED;
+    }
+
+    // SMM Related Protocol
+    if (ExportedInterfaceHob->SmmBase2Protocol != 0) {
+      Handle = NULL;
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &Handle,
+                      &gEfiSmmBase2ProtocolGuid,
+                      ExportedInterfaceHob->SmmBase2Protocol,
+                      NULL
+                      );
+      if ( EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "Failed to install SMM Base 2 Protocol!\n"));
+        return Status;
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "SMM Base 2 Protocol address is 0!\n"));
+      return EFI_UNSUPPORTED;
+    }
+
+    if (ExportedInterfaceHob->SmmCommunicationProtocol != 0) {
+      Handle = NULL;
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &Handle,
+                      &gEfiSmmCommunicationProtocolGuid,
+                      ExportedInterfaceHob->SmmCommunicationProtocol,
+                      NULL
+                      );
+      if ( EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "Failed to install SMM Communication Protocol!\n"));
+        return Status;
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "SMM Communication Protocol address is 0!\n"));
+      return EFI_UNSUPPORTED;
+    }
+
+    if (ExportedInterfaceHob->MmCommunication2Protocol != 0) {
+      Handle = NULL;
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &Handle,
+                      &gEfiMmCommunication2ProtocolGuid,
+                      ExportedInterfaceHob->MmCommunication2Protocol,
+                      NULL
+                      );
+      if ( EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "Failed to install MM Communication 2 Protocol!\n"));
+        return Status;
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "MM Communication 2 Protocol address is 0!\n"));
+      return EFI_UNSUPPORTED;
+    }
+
+    if (ExportedInterfaceHob->PspFtpmProtocol != 0) {
+      Handle = NULL;
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &Handle,
+                      &gAmdPspFtpmProtocolGuid,
+                      ExportedInterfaceHob->PspFtpmProtocol,
+                      NULL
+                      );
+      if ( EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "Failed to install PSP fTPM Protocol!\n"));
+        return Status;
+      }
+    } else {
+      DEBUG ((DEBUG_ERROR, "PSP fTPM Protocol address is 0!\n"));
+      return EFI_UNSUPPORTED;
+    }
+
+    if (ExportedInterfaceHob->FchResetSystem != 0) {
+      gST->RuntimeServices->ResetSystem = ExportedInterfaceHob->FchResetSystem;
+      Handle                            = NULL;
+      gBS->InstallProtocolInterface (
+             &Handle,
+             &gEfiResetArchProtocolGuid,
+             EFI_NATIVE_INTERFACE,
+             NULL
+             );
+    } else {
+      DEBUG ((DEBUG_ERROR, "Runtime Reset address is 0!\n"));
+      return EFI_UNSUPPORTED;
+    }
+
+    // Install SMBIOS Protocol.
+    EFI_SMBIOS_PROTOCOL  *SmbiosProtocol;
+    VOID                 **SmbiosTableAddress = ExportedInterfaceHob->SmbiosPointers;
+    Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&SmbiosProtocol);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "SMBIOS Protocol not found!\n"));
+      return EFI_NOT_FOUND;
+    }
+
+    for (UINT32 Count = 0; Count < MAX_SMBIOS_TABLE_COUNT; Count++) {
+      if (SmbiosTableAddress[Count]) {
+        EFI_SMBIOS_TABLE_HEADER  *Header = (VOID *)((UINTN)SmbiosTableAddress[Count]);
+        Header->Handle = SMBIOS_HANDLE_PI_RESERVED; // Re-allocate one.
+        Status         = SmbiosProtocol->Add (SmbiosProtocol, NULL, &Header->Handle, Header);
+        if (EFI_ERROR (Status)) {
+          DEBUG ((DEBUG_ERROR, "Failed to add SMBIOS Entry #%d @0x%x:%r!\n", Count, SmbiosTableAddress[Count], Status));
+          break;
+        }
+
+        DEBUG ((DEBUG_INFO, "Added SMBIOS Entry #%d @0x%x\n", Count, SmbiosTableAddress[Count]));
+      }
+    }
+
+    // Set PcdAmdSmmCommunicationAddress.
+    PcdSet64S (PcdAmdSmmCommunicationAddress, ExportedInterfaceHob->PcdAmdSmmCommunicationAddress);
+    PcdSet64S (PcdAmdS3LibPrivateDataAddress, ExportedInterfaceHob->PcdAmdS3LibPrivateDataAddress);
+    PcdSet64S (PcdAmdS3LibTableAddress, ExportedInterfaceHob->PcdAmdS3LibTableAddress);
+    PcdSet64S (PcdAmdS3LibTableSize, ExportedInterfaceHob->PcdAmdS3LibTableSize);
+    PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, ExportedInterfaceHob->S3BootScriptTablePrivateDataPtr);
+    PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, ExportedInterfaceHob->S3BootScriptTablePrivateSmmDataPtr);
+    DEBUG ((
+      DEBUG_INFO,
+      "PcdS3BootScriptTablePrivateDataPtr:%011p,PcdS3BootScriptTablePrivateSmmDataPtr:%011p\n",
+      ExportedInterfaceHob->S3BootScriptTablePrivateDataPtr,
+      ExportedInterfaceHob->S3BootScriptTablePrivateSmmDataPtr
+      ));
+    DEBUG ((DEBUG_INFO, "Offset:%p,%p\n", &ExportedInterfaceHob->S3BootScriptTablePrivateDataPtr, &ExportedInterfaceHob->S3BootScriptTablePrivateSmmDataPtr));
+    ASSERT (
+      EfiNamedEventListen (
+        &gFspSmmDependencyReadyProtocolGuid,
+        TPL_CALLBACK,
+        OnRuntimeServiceReady,
+        NULL,
+        NULL
+        ) == EFI_SUCCESS
+      );
+    gBS->InstallProtocolInterface (
+           &Handle,
+           &gPspFlashAccSmmCommReadyProtocolGuid,
+           EFI_NATIVE_INTERFACE,
+           NULL
+           );
+    // Install Smm Variable Write protocol.
+    Handle = NULL;
+    gBS->InstallMultipleProtocolInterfaces (
+           &Handle,
+           &gEfiSmmVariableProtocolGuid,
+           NULL,
+           &gSmmVariableWriteGuid,
+           NULL,
+           &gEfiLockBoxProtocolGuid,
+           NULL,
+           NULL
+           );
+  } else {
+    DEBUG ((DEBUG_ERROR, "FspsUpdHob is NULL!\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.inf
new file mode 100644
index 0000000000..bfba777aab
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.inf
@@ -0,0 +1,79 @@
+## @file
+#  FSP wrapper to handle FSP MultiPhase (SeparatePhase) Initialization.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = DxeFspWrapperMultiPhaseProcessLib
+  FILE_GUID                      = 221219AB-C75F-450B-A961-978C59E42C83
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FspWrapperMultiPhaseProcessLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources]
+  DxeFspWrapperMultiPhaseProcessLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  AgesaPublic/AgesaPublic.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  BaseLib
+  PcdLib
+  FspWrapperPlatformMultiPhaseLib
+
+[Guids]
+  gFspsUpdDataPointerAddressGuid        ## CONSUMES
+  gSmmVariableWriteGuid                 ## PRODUCES
+  gFspHobGuid                           ## CONSUMES
+  gFspExportedInterfaceHobGuid          ## CONSUMES
+
+[Protocols]
+  gEfiSmbiosProtocolGuid                ## CONSUMES
+  gEfiVariableArchProtocolGuid          ## CONSUMES
+  gEfiSmmVariableProtocolGuid           ## PRODUCES
+  gPspFlashAccSmmCommReadyProtocolGuid  ## PRODUCES
+  gEfiGlobalNvsAreaProtocolGuid         ## CONSUMES
+  gFspSmmDependencyReadyProtocolGuid    ## CONSUMES
+  gEfiHiiDatabaseProtocolGuid           ## CONSUMES
+  gEfiHiiStringProtocolGuid             ## CONSUMES
+  gEfiHiiConfigRoutingProtocolGuid      ## CONSUMES
+  gEfiLockBoxProtocolGuid               ## PRODUCES
+  gAmdPspFtpmProtocolGuid               ## PRODUCES
+
+[Ppis]
+
+[Pcd]
+  gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInMemory      ## CONSUMES
+  gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInMemory      ## CONSUMES
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdSmmCommunicationAddress ## PRODUCES FROM_FSP
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdS3LibPrivateDataAddress ## PRODUCES FROM_FSP
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdS3LibTableAddress       ## PRODUCES FROM_FSP
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdS3LibTableSize          ## PRODUCES FROM_FSP
+  gEfiMdeModulePkgTokenSpaceGuid.PcdS3BootScriptTablePrivateDataPtr ## PRODUCES FROM_FSP
+  gEfiMdeModulePkgTokenSpaceGuid.PcdS3BootScriptTablePrivateSmmDataPtr  ## PRODUCES FROM_FSP
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase      ## CONSUMES   BY_FSP
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize      ## CONSUMES   BY_FSP
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase    ## CONSUMES   BY_FSP
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize    ## CONSUMES   BY_FSP
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase      ## CONSUMES   BY_FSP
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize      ## CONSUMES   BY_FSP
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
new file mode 100644
index 0000000000..207cea801f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
@@ -0,0 +1,49 @@
+## @file
+#  FSP wrapper to handle FSP MultiPhase (SeparatePhase) Initialization.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = FspWrapperMultiPhaseProcessLib
+  FILE_GUID                      = 11E657B7-C3D8-405B-94C5-516840E67B75
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FspWrapperMultiPhaseProcessLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+[Sources]
+  PeiFspWrapperMultiPhaseProcessLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  BaseLib
+  PcdLib
+  FspWrapperPlatformLib
+  PeiServicesLib
+  FspWrapperPlatformMultiPhaseLib
+
+[Ppis]
+  gEfiPeiReadOnlyVariable2PpiGuid
+  gEdkiiPeiVariablePpiGuid
+
+[Pcd]
+  gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInMemory      ## CONSUMES
+  gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInMemory      ## CONSUMES
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
new file mode 100644
index 0000000000..e072efbb04
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
@@ -0,0 +1,385 @@
+/** @file
+  Support FSP Wrapper MultiPhase process.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <FspEas.h>
+#include <FspGlobalData.h>
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/Variable.h>
+#include <Library/PeiServicesLib.h>
+#include "../../Include/Library/FspWrapperPlatformMultiPhaseLib.h"
+#include <MultiPhaseSiPhases.h>
+
+// The EDK 202208 Doesn't hold these structs.
+typedef enum {
+  EnumMultiPhaseGetVariableRequestInfo  = 0x2,
+  EnumMultiPhaseCompleteVariableRequest = 0x3
+} FSP_MULTI_PHASE_ACTION_23;
+
+typedef enum {
+  FspMultiPhaseMemInitApiIndex = 8
+} FSP_API_INDEX_23;
+///
+/// Action definition for FspMultiPhaseSiInit API
+///
+typedef enum {
+  EnumFspVariableRequestGetVariable         = 0x0,
+  EnumFspVariableRequestGetNextVariableName = 0x1,
+  EnumFspVariableRequestSetVariable         = 0x2,
+  EnumFspVariableRequestQueryVariableInfo   = 0x3
+} FSP_VARIABLE_REQUEST_TYPE;
+
+#pragma pack(16)
+typedef struct {
+  IN     FSP_VARIABLE_REQUEST_TYPE    VariableRequest;
+  IN OUT CHAR16                       *VariableName;
+  IN OUT UINT64                       *VariableNameSize;
+  IN OUT EFI_GUID                     *VariableGuid;
+  IN OUT UINT32                       *Attributes;
+  IN OUT UINT64                       *DataSize;
+  IN OUT VOID                         *Data;
+  OUT    UINT64                       *MaximumVariableStorageSize;
+  OUT    UINT64                       *RemainingVariableStorageSize;
+  OUT    UINT64                       *MaximumVariableSize;
+} FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS;
+
+typedef struct {
+  EFI_STATUS    VariableRequestStatus;
+} FSP_MULTI_PHASE_COMPLETE_VARIABLE_REQUEST_PARAMS;
+
+#pragma pack()
+
+/**
+  Execute 32-bit FSP API entry code.
+
+  @param[in] Function     The 32bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 32bit code.
+  @param[in] Param2       The second parameter to pass to 32bit code.
+
+  @return EFI_STATUS.
+**/
+EFI_STATUS
+Execute32BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  );
+
+/**
+  Execute 64-bit FSP API entry code.
+
+  @param[in] Function     The 64bit code entry to be executed.
+  @param[in] Param1       The first parameter to pass to 64bit code.
+  @param[in] Param2       The second parameter to pass to 64bit code.
+
+  @return EFI_STATUS.
+**/
+EFI_STATUS
+Execute64BitCode (
+  IN UINT64  Function,
+  IN UINT64  Param1,
+  IN UINT64  Param2
+  );
+
+/**
+  Call FspsMultiPhase API.
+
+  @param[in] FspsMultiPhaseParams - Parameters for MultiPhase API.
+  @param[in] FspHobListPtr        - Pointer to FSP HobList (valid after FSP-M completed)
+  @param[in] ComponentIndex       - FSP Component which executing MultiPhase initialization.
+
+  @return EFI_UNSUPPORTED  - the requested FspsMultiPhase API is not supported.
+  @return EFI_DEVICE_ERROR - the FSP header was not found.
+  @return EFI status returned by FspsMultiPhase API.
+**/
+EFI_STATUS
+EFIAPI
+CallFspMultiPhaseEntry (
+  IN VOID      *FspMultiPhaseParams,
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex
+  )
+{
+  FSP_INFO_HEADER  *FspHeader;
+  //
+  // FSP_MULTI_PHASE_INIT and FSP_MULTI_PHASE_SI_INIT API functions having same prototype.
+  //
+  UINTN                   FspMultiPhaseApiEntry;
+  UINTN                   FspMultiPhaseApiOffset = 0;
+  EFI_STATUS              Status;
+  BOOLEAN                 InterruptState;
+  BOOLEAN                 IsVariableServiceRequest;
+  FSP_MULTI_PHASE_PARAMS  *FspMultiPhaseParamsPtr;
+
+  FspMultiPhaseParamsPtr   = (FSP_MULTI_PHASE_PARAMS *)FspMultiPhaseParams;
+  IsVariableServiceRequest = FALSE;
+  if ((FspMultiPhaseParamsPtr->MultiPhaseAction == (int)EnumMultiPhaseGetVariableRequestInfo) ||
+      (FspMultiPhaseParamsPtr->MultiPhaseAction == (int)EnumMultiPhaseCompleteVariableRequest))
+  {
+    IsVariableServiceRequest = TRUE;
+  }
+
+  if (ComponentIndex == FspMultiPhaseMemInitApiIndex) {
+    FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddressInMemory));
+    if (FspHeader == NULL) {
+      return EFI_DEVICE_ERROR;
+    } else if (FspHeader->SpecVersion < 0x24) {
+      return EFI_UNSUPPORTED;
+    }
+
+    FspMultiPhaseApiOffset = FspHeader->FspMultiPhaseMemInitEntryOffset;
+  } else if (ComponentIndex == FspMultiPhaseSiInitApiIndex) {
+    FspHeader = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddressInMemory));
+    if (FspHeader == NULL) {
+      return EFI_DEVICE_ERROR;
+    } else if (FspHeader->SpecVersion < 0x22) {
+      return EFI_UNSUPPORTED;
+    } else if ((FspHeader->SpecVersion < 0x24) && (IsVariableServiceRequest == TRUE)) {
+      return EFI_UNSUPPORTED;
+    }
+
+    FspMultiPhaseApiOffset = FspHeader->FspMultiPhaseSiInitEntryOffset;
+  }
+
+  if (FspMultiPhaseApiOffset == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  FspMultiPhaseApiEntry = FspHeader->ImageBase + FspMultiPhaseApiOffset;
+  InterruptState        = SaveAndDisableInterrupts ();
+  if ((FspHeader->ImageAttribute & BIT2) == 0) {
+    // BIT2: IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT
+    Status = Execute32BitCode ((UINTN)FspMultiPhaseApiEntry, (UINTN)FspMultiPhaseParams, (UINTN)NULL);
+  } else {
+    Status = Execute64BitCode ((UINTN)FspMultiPhaseApiEntry, (UINTN)FspMultiPhaseParams, (UINTN)NULL);
+  }
+
+  SetInterruptState (InterruptState);
+
+  DEBUG ((DEBUG_ERROR, "CallFspMultiPhaseEntry return Status %r \n", Status));
+
+  return Status;
+}
+
+/**
+  FSP Wrapper Variable Request Handler
+
+  @param[in, out] FspHobListPtr        - Pointer to FSP HobList (valid after FSP-M completed)
+  @param[in]      ComponentIndex       - FSP Component which executing MultiPhase initialization.
+
+  @retval EFI_UNSUPPORTED   FSP Wrapper cannot support the specific variable request,
+                            or FSP does not support VariableService
+  @retval EFI_STATUS        Return FSP returned status
+
+**/
+EFI_STATUS
+EFIAPI
+FspWrapperVariableRequestHandler (
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex
+  )
+{
+  EFI_STATUS                                        Status;
+  FSP_MULTI_PHASE_PARAMS                            FspMultiPhaseParams;
+  FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS      *FspVariableRequestParams;
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI                   *ReadOnlyVariablePpi;
+  EDKII_PEI_VARIABLE_PPI                            *VariablePpi;
+  BOOLEAN                                           WriteVariableSupport;
+  FSP_MULTI_PHASE_COMPLETE_VARIABLE_REQUEST_PARAMS  CompleteVariableRequestParams;
+
+  WriteVariableSupport = TRUE;
+  Status               = PeiServicesLocatePpi (
+                           &gEdkiiPeiVariablePpiGuid,
+                           0,
+                           NULL,
+                           (VOID **)&VariablePpi
+                           );
+  if (EFI_ERROR (Status)) {
+    WriteVariableSupport = FALSE;
+    Status               = PeiServicesLocatePpi (
+                             &gEfiPeiReadOnlyVariable2PpiGuid,
+                             0,
+                             NULL,
+                             (VOID **)&ReadOnlyVariablePpi
+                             );
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR (Status)) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  Status = FSP_STATUS_VARIABLE_REQUEST;
+  while (Status == FSP_STATUS_VARIABLE_REQUEST) {
+    //
+    // Get the variable request information from FSP.
+    //
+    FspMultiPhaseParams.MultiPhaseAction = (int)EnumMultiPhaseGetVariableRequestInfo;
+    FspMultiPhaseParams.PhaseIndex       = 0;
+    Status                               = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
+    ASSERT_EFI_ERROR (Status);
+    //
+    // FSP should output this pointer for variable request information.
+    //
+    FspVariableRequestParams = (FSP_MULTI_PHASE_VARIABLE_REQUEST_INFO_PARAMS *)FspMultiPhaseParams.MultiPhaseParamPtr;
+    switch (FspVariableRequestParams->VariableRequest) {
+      case EnumFspVariableRequestGetVariable:
+        if (WriteVariableSupport) {
+          Status = VariablePpi->GetVariable (
+                                  VariablePpi,
+                                  FspVariableRequestParams->VariableName,
+                                  FspVariableRequestParams->VariableGuid,
+                                  FspVariableRequestParams->Attributes,
+                                  (UINTN *)FspVariableRequestParams->DataSize,
+                                  FspVariableRequestParams->Data
+                                  );
+        } else {
+          Status = ReadOnlyVariablePpi->GetVariable (
+                                          ReadOnlyVariablePpi,
+                                          FspVariableRequestParams->VariableName,
+                                          FspVariableRequestParams->VariableGuid,
+                                          FspVariableRequestParams->Attributes,
+                                          (UINTN *)FspVariableRequestParams->DataSize,
+                                          FspVariableRequestParams->Data
+                                          );
+        }
+
+        CompleteVariableRequestParams.VariableRequestStatus = Status;
+        FspMultiPhaseParams.MultiPhaseParamPtr              = (VOID *)&CompleteVariableRequestParams;
+        FspMultiPhaseParams.MultiPhaseAction                = (int)EnumMultiPhaseCompleteVariableRequest;
+        Status                                              = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
+        break;
+
+      case EnumFspVariableRequestSetVariable:
+        if (WriteVariableSupport) {
+          Status = VariablePpi->SetVariable (
+                                  VariablePpi,
+                                  FspVariableRequestParams->VariableName,
+                                  FspVariableRequestParams->VariableGuid,
+                                  *FspVariableRequestParams->Attributes,
+                                  (UINTN)*FspVariableRequestParams->DataSize,
+                                  FspVariableRequestParams->Data
+                                  );
+        } else {
+          Status = EFI_UNSUPPORTED;
+        }
+
+        CompleteVariableRequestParams.VariableRequestStatus = Status;
+        FspMultiPhaseParams.MultiPhaseParamPtr              = (VOID *)&CompleteVariableRequestParams;
+        FspMultiPhaseParams.MultiPhaseAction                = (int)EnumMultiPhaseCompleteVariableRequest;
+        Status                                              = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
+        break;
+
+      case EnumFspVariableRequestGetNextVariableName:
+        if (WriteVariableSupport) {
+          Status = VariablePpi->GetNextVariableName (
+                                  VariablePpi,
+                                  (UINTN *)FspVariableRequestParams->VariableNameSize,
+                                  FspVariableRequestParams->VariableName,
+                                  FspVariableRequestParams->VariableGuid
+                                  );
+        } else {
+          Status = ReadOnlyVariablePpi->NextVariableName (
+                                          ReadOnlyVariablePpi,
+                                          (UINTN *)FspVariableRequestParams->VariableNameSize,
+                                          FspVariableRequestParams->VariableName,
+                                          FspVariableRequestParams->VariableGuid
+                                          );
+        }
+
+        CompleteVariableRequestParams.VariableRequestStatus = Status;
+        FspMultiPhaseParams.MultiPhaseParamPtr              = (VOID *)&CompleteVariableRequestParams;
+        FspMultiPhaseParams.MultiPhaseAction                = (int)EnumMultiPhaseCompleteVariableRequest;
+        Status                                              = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
+        break;
+
+      case EnumFspVariableRequestQueryVariableInfo:
+        if (WriteVariableSupport) {
+          Status = VariablePpi->QueryVariableInfo (
+                                  VariablePpi,
+                                  *FspVariableRequestParams->Attributes,
+                                  FspVariableRequestParams->MaximumVariableStorageSize,
+                                  FspVariableRequestParams->RemainingVariableStorageSize,
+                                  FspVariableRequestParams->MaximumVariableSize
+                                  );
+        } else {
+          Status = EFI_UNSUPPORTED;
+        }
+
+        CompleteVariableRequestParams.VariableRequestStatus = Status;
+        FspMultiPhaseParams.MultiPhaseParamPtr              = (VOID *)&CompleteVariableRequestParams;
+        FspMultiPhaseParams.MultiPhaseAction                = (int)EnumMultiPhaseCompleteVariableRequest;
+        Status                                              = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
+        break;
+
+      default:
+        DEBUG ((DEBUG_ERROR, "Unknown VariableRequest type!\n"));
+        Status = EFI_UNSUPPORTED;
+        break;
+    }
+  }
+
+  //
+  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
+  //
+  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
+    DEBUG ((DEBUG_INFO, "FspMultiPhaseApi-0x%x requested reset %r\n", ComponentIndex, Status));
+    CallFspWrapperResetSystem ((UINTN)Status);
+  }
+
+  return Status;
+}
+
+/**
+  FSP Wrapper MultiPhase Handler
+
+  @param[in, out] FspHobListPtr        - Pointer to FSP HobList (valid after FSP-M completed)
+  @param[in]      ComponentIndex       - FSP Component which executing MultiPhase initialization.
+
+  @retval EFI_UNSUPPORTED   Specific MultiPhase action was not supported.
+  @retval EFI_SUCCESS       MultiPhase action were completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+FspWrapperMultiPhaseHandler (
+  IN OUT VOID  **FspHobListPtr,
+  IN UINT8     ComponentIndex
+  )
+{
+  EFI_STATUS                                   Status;
+  FSP_MULTI_PHASE_PARAMS                       FspMultiPhaseParams;
+  FSP_MULTI_PHASE_GET_NUMBER_OF_PHASES_PARAMS  FspMultiPhaseGetNumber;
+  // UINT32                                       Index;
+  UINT32  NumOfPhases;
+
+  //
+  // Query FSP for the number of phases supported.
+  //
+  FspMultiPhaseParams.MultiPhaseAction   = EnumMultiPhaseGetNumberOfPhases;
+  FspMultiPhaseParams.PhaseIndex         = 0;
+  FspMultiPhaseParams.MultiPhaseParamPtr = (VOID *)&FspMultiPhaseGetNumber;
+  Status                                 = CallFspMultiPhaseEntry (&FspMultiPhaseParams, FspHobListPtr, ComponentIndex);
+  if (Status == EFI_UNSUPPORTED) {
+    //
+    // MultiPhase API was not supported
+    //
+    return Status;
+  } else {
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  NumOfPhases = FspMultiPhaseGetNumber.NumberOfPhases;
+  DEBUG ((DEBUG_INFO, "Multi Phase Si Init: Total %d phases.\n", NumOfPhases));
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/FspWrapperApiTest.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/FspWrapperApiTest.c
new file mode 100644
index 0000000000..caffada924
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/FspWrapperApiTest.c
@@ -0,0 +1,85 @@
+/** @file
+  Provide FSP wrapper API test related function.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Guid/GuidHobFspEas.h>
+
+/**
+  Test the output of FSP API - FspMemoryInit.
+
+  @param[in]  FspmUpdDataPtr Address pointer to the FSP_MEMORY_INIT_PARAMS structure.
+  @param[in]  HobListPtr     Address of the HobList pointer.
+
+  @return test result on output of FspMemoryInit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspMemoryInitApiOutput (
+  IN  VOID  *FspmUpdDataPtr,
+  IN  VOID  **HobListPtr
+  )
+{
+  DEBUG_CODE_BEGIN ();
+  EFI_PEI_HOB_POINTERS  Hob;
+
+  Hob.Raw = (UINT8 *)(*(HobListPtr));
+  while (TRUE) {
+    if (END_OF_HOB_LIST (Hob) == TRUE) {
+      DEBUG ((DEBUG_INFO, "gFspBootLoaderTolumHobGuid not Found\n"));
+      break;
+    }
+
+    if ((CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspBootLoaderTolumHobGuid))) {
+      DEBUG ((DEBUG_INFO, "gFspBootLoaderTolumHobGuid Found\n"));
+      DEBUG ((DEBUG_INFO, "Fill Boot Loader reserved memory range with 0x5A for testing purpose\n"));
+      SetMem ((VOID *)(UINTN)Hob.ResourceDescriptor->PhysicalStart, (UINTN)Hob.ResourceDescriptor->ResourceLength, 0x5A);
+      break;
+    }
+
+    Hob.Raw = GET_NEXT_HOB (Hob);
+  }
+
+  DEBUG_CODE_END ();
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Test the output of FSP API - TempRamExit.
+
+  @param[in] TempRamExitParam    Address pointer to the TempRamExit parameters structure.
+
+  @return test result on output of TempRamExit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspTempRamExitApiOutput (
+  IN VOID  *TempRamExitParam
+  )
+{
+  return RETURN_SUCCESS;
+}
+
+/**
+  Test the output of FSP API - FspSiliconInit.
+
+  @param[in] FspsUpdDataPtr Address pointer to the Silicon Init parameters structure.
+
+  @return test result on output of FspSiliconInit API.
+**/
+EFI_STATUS
+EFIAPI
+TestFspSiliconInitApiOutput (
+  IN  VOID  *FspsUpdDataPtr
+  )
+{
+  return RETURN_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
new file mode 100644
index 0000000000..7b2d4b0837
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
@@ -0,0 +1,52 @@
+### @file
+#  Provide FSP-M wrapper API test related function.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (C) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010017
+  BASE_NAME                      = PeiFspWrapperApiTestLib
+  FILE_GUID                      = 87DC266A-C8F7-4A66-A0CB-018A6F5305B4
+  VERSION_STRING                 = 1.0
+  MODULE_TYPE                    = PEIM
+  LIBRARY_CLASS                  = FspWrapperApiTestLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+  FspWrapperApiTest.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+
+[Packages]
+  MdePkg/MdePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  HobLib
+
+[Guids]
+  gFspBootLoaderTolumHobGuid            ## SOMETIMES_CONSUMES ## GUID
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/CommonHeader.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/CommonHeader.h
new file mode 100644
index 0000000000..f4f08432cf
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/CommonHeader.h
@@ -0,0 +1,91 @@
+/** @file
+  Implements CommonHeader.h
+
+  Copyright (c) 2013 - 2016 Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 <Fch.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/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
+
+EFI_STATUS
+GetAvailableMemoryRanges (
+  IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE  *MemoryMap,
+  IN OUT UINT8                                  *NumRanges,
+  IN VOID                                       *FspHobList
+  );
+
+EFI_STATUS
+GetReservedMemoryRanges (
+  IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE  *MemoryMap,
+  IN OUT UINT8                                  *NumRanges,
+  IN VOID                                       *FspHobList
+  );
+
+EFI_STATUS
+GetMemorySize (
+  IN  CONST EFI_PEI_SERVICES  **PeiServices,
+  OUT UINT64                  *LowMemoryLength,
+  OUT UINT64                  *HighMemoryLength,
+  OUT UINT64                  *GraphicMemoryBase OPTIONAL,
+  OUT UINT64                  *GraphicMemoryLength OPTIONAL,
+  IN VOID                     *FspHobList
+  );
+
+EFI_STATUS
+EFIAPI
+SetPeiCacheMode (
+  IN  CONST EFI_PEI_SERVICES  **PeiServices,
+  IN  VOID                    *FspHobList
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
new file mode 100644
index 0000000000..3100f4635e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
@@ -0,0 +1,1439 @@
+/** @file
+  Sample to provide FSP wrapper hob process related function.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CommonHeader.h"
+#include <Ppi/AmdPspFtpmPpi.h>
+#include <Ppi/Reset2.h>
+#include <FspEas/FspApi.h>
+#include <FspmUpd.h>
+#include <Library/PeiServicesLib.h>
+#include <FspMemoryRegionHob.h>
+#include <FspExportedInterfaceHob.h>
+
+#define MTRR_LIB_CACHE_MTRR_ENABLED  0x800
+
+extern EFI_GUID  gAmdResourceSizeForEachRbGuid;
+
+EFI_MEMORY_TYPE_INFORMATION  mDefaultMemoryTypeInformation[] = {
+  { EfiACPIReclaimMemory,       0x40   },
+  { EfiACPIMemoryNVS,           0x20   },
+  { EfiReservedMemoryType,      0x10   },
+  { EfiMemoryMappedIO,          0      },
+  { EfiMemoryMappedIOPortSpace, 0      },
+  { EfiPalCode,                 0      },
+  { EfiRuntimeServicesCode,     0x80   },
+  { EfiRuntimeServicesData,     0x40   },
+  { EfiLoaderCode,              0      },
+  { EfiLoaderData,              0      },
+  { EfiBootServicesCode,        0x400  },
+  { EfiBootServicesData,        0x1000 },
+  { EfiConventionalMemory,      0x4    },
+  { EfiUnusableMemory,          0      },
+  { EfiMaxMemoryType,           0      }
+};
+
+#pragma pack (push,4) // AGESA BUG
+typedef struct _APOBLIB_INFO {
+  BOOLEAN    Supported;              ///<  Specify if APOB supported
+  UINT32     ApobSize;               ///<  ApobSize
+  UINT64     ApobAddr;               ///<  The Address of APOB
+} APOBLIB_INFO;
+#pragma pack (pop)
+STATIC_ASSERT (sizeof (APOBLIB_INFO) == 16, "APOB Hob not aligned as MSVC behavior!");
+
+/**
+
+  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.
+
+  @return MemoryMap     The buffer will be filled in
+          NumRanges     will contain the actual number of memory ranges that are to be anabled.
+          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,
+  IN     VOID                                   *FspHobList
+  )
+{
+  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, FspHobList);
+
+  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, FspHobList);
+  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) {
+      SmRamTsegLength                             = (BlockNum * 128 * 1024);
+      MemoryMap[*NumRanges].RangeLength           = SmRamTsegLength;
+      MemorySize                                 -= MemoryMap[*NumRanges].RangeLength;
+      MemoryMap[*NumRanges].PhysicalAddress       = MemorySize;
+      MemoryMap[*NumRanges].CpuAddress            = MemorySize;
+      SmRamTsegBase                               = MemorySize;
+      MemoryMap[ExtendedMemoryIndex].RangeLength -= MemoryMap[*NumRanges].RangeLength;
+
+      //
+      // Turn On Smram
+      //
+      SmRamTsegMask = (0x0000010000000000L-SmRamTsegLength) & 0xFFFFFFFE0000UL; // TSegMask[47:17]
+      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.
+
+  @return  EFI_SUCCESS            The function completed successfully.
+           EFI_INVALID_PARAMETER  One of the input parameters was invalid.
+           EFI_ABORTED            An error occurred.
+
+**/
+EFI_STATUS
+InstallEfiMemory (
+  IN      EFI_PEI_SERVICES  **PeiServices,
+  IN      EFI_BOOT_MODE     BootMode,
+  IN      VOID              *FspHobList
+  )
+{
+  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,
+             FspHobList
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "NumRanges: %d\n", NumRanges));
+
+  DEBUG ((DEBUG_INFO, "GetMemoryMap:\n"));
+  for (Index = 0; Index < NumRanges; Index++) {
+    DEBUG ((DEBUG_INFO, "Index: %d ", Index));
+    DEBUG ((DEBUG_INFO, "RangeLength: 0x%016lX\t", MemoryMap[Index].RangeLength));
+    DEBUG ((DEBUG_INFO, "PhysicalAddress: 0x%016lX\t", MemoryMap[Index].PhysicalAddress));
+    DEBUG ((DEBUG_INFO, "CpuAddress: 0x%016lX\t", MemoryMap[Index].CpuAddress));
+    DEBUG ((DEBUG_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 ((DEBUG_INFO, "Found 0x%lx bytes at ", MemoryMap[Index].RangeLength));
+    DEBUG ((DEBUG_INFO, "0x%lx.\t", MemoryMap[Index].PhysicalAddress));
+    DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_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.
+
+  @return EFI_SUCCESS  The function completed successfully.
+                       Error value from LocatePpi()
+
+**/
+EFI_STATUS
+InstallS3Memory (
+  IN      EFI_PEI_SERVICES  **PeiServices,
+  IN      EFI_BOOT_MODE     BootMode,
+  IN      VOID              *FspHobList
+  )
+{
+  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,
+             FspHobList
+             );
+  ASSERT_EFI_ERROR (Status);
+  DEBUG ((DEBUG_INFO, "NumRanges = 0x%x\n", NumRanges));
+
+  //
+  // Install physical memory descriptor hobs for each memory range.
+  //
+  SmramRanges = 0;
+  DEBUG ((DEBUG_INFO, "GetMemoryMap:\n"));
+  for (Index = 0; Index < NumRanges; Index++) {
+    DEBUG ((DEBUG_INFO, "Index: %d ", Index));
+    DEBUG ((DEBUG_INFO, "RangeLength: 0x%016lX\t", MemoryMap[Index].RangeLength));
+    DEBUG ((DEBUG_INFO, "PhysicalAddress: 0x%016lX\t", MemoryMap[Index].PhysicalAddress));
+    DEBUG ((DEBUG_INFO, "CpuAddress: 0x%016lX\t", MemoryMap[Index].CpuAddress));
+    DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_INFO, "BufferSize = 0x%x\n", BufferSize));
+
+  Hob.Raw = BuildGuidHob (
+              &gEfiSmmPeiSmramMemoryReserveGuid,
+              BufferSize
+              );
+  ASSERT (Hob.Raw);
+  DEBUG ((DEBUG_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 ((DEBUG_INFO, "Index: 0x%X \t", Index));
+    DEBUG ((DEBUG_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 ((DEBUG_INFO, "SmramIndex: 0x%X \n", SmramIndex));
+      DEBUG ((DEBUG_INFO, "PhysicalStart: 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart));
+      DEBUG ((DEBUG_INFO, "CpuStart     : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart));
+      DEBUG ((DEBUG_INFO, "PhysicalSize : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize));
+      DEBUG ((DEBUG_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 ((DEBUG_INFO, "SmramIndex: 0x%X \n", SmramIndex));
+        DEBUG ((DEBUG_INFO, "PhysicalStart: 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart));
+        DEBUG ((DEBUG_INFO, "CpuStart     : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart));
+        DEBUG ((DEBUG_INFO, "PhysicalSize : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize));
+        DEBUG ((DEBUG_INFO, "RegionState  : 0x%X\n\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState));
+
+        DEBUG ((DEBUG_INFO, "PhysicalSize : 0x%X\n", (UINTN)SmramHobDescriptorBlock->Descriptor[SmramIndex-1].PhysicalSize));
+        DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_INFO, "TSEG Base = 0x%08x\n", SmramHobDescriptorBlock->Descriptor[SmramRanges].PhysicalStart));
+  DEBUG ((DEBUG_INFO, "SmramRanges = 0x%x\n", SmramRanges));
+  S3MemoryRangeData = (RESERVED_ACPI_S3_RANGE *)(UINTN)
+                      (SmramHobDescriptorBlock->Descriptor[SmramRanges].PhysicalStart + RESERVED_ACPI_S3_RANGE_OFFSET);
+  DEBUG ((DEBUG_INFO, "S3MemoryRangeData = 0x%08x\n", (UINTN)S3MemoryRangeData));
+
+  DEBUG ((DEBUG_INFO, "S3MemoryRangeData->AcpiReservedMemoryBase = 0x%X\n", (UINTN)S3MemoryRangeData->AcpiReservedMemoryBase));
+  DEBUG ((DEBUG_INFO, "S3MemoryRangeData->AcpiReservedMemorySize = 0x%X\n", (UINTN)S3MemoryRangeData->AcpiReservedMemorySize));
+  DEBUG ((DEBUG_INFO, "S3MemoryRangeData->SystemMemoryLength = 0x%X\n", (UINTN)S3MemoryRangeData->SystemMemoryLength));
+
+  S3MemoryBase = (UINTN)(S3MemoryRangeData->AcpiReservedMemoryBase);
+  DEBUG ((DEBUG_INFO, "S3MemoryBase = 0x%08x\n", S3MemoryBase));
+  S3MemorySize = (UINTN)(S3MemoryRangeData->AcpiReservedMemorySize);
+  DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_INFO, "MemoryBegin: 0x%lX, MemoryLength: 0x%lX\n", MemoryMap[Index].PhysicalAddress, MemoryMap[Index].RangeLength));
+
+      DEBUG ((DEBUG_INFO, "Build resource HOB for Legacy Region on S3 patch :"));
+      DEBUG ((DEBUG_INFO, " Memory Base:0x%lX Length:0x%lX\n", MemoryMap[Index].PhysicalAddress, MemoryMap[Index].RangeLength));
+    }
+  }
+
+  AsmMsrOr64 (0xC0010113, 0x4403); // Enable SMRAM
+  return EFI_SUCCESS;
+}
+
+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 ((DEBUG_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 ((DEBUG_INFO, "GetPlatformMemorySize, MemorySize: 0x%lX\n", *MemorySize));
+  return EFI_SUCCESS;
+}
+
+/**
+  Post FSP-M HOB process for Memory Resource Descriptor.
+
+  @param[in] FspHobList  Pointer to the HOB data structure produced by FSP.
+
+  @return If platform process the FSP hob list successfully.
+**/
+EFI_STATUS
+EFIAPI
+PostFspmHobProcess (
+  IN VOID  *FspHobList
+  )
+{
+  EFI_STATUS        Status;
+  EFI_BOOT_MODE     BootMode;
+  EFI_PEI_SERVICES  **PeiServices;
+
+  PreFspmHobProcess (FspHobList);
+
+  PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer ();
+  //
+  // Get boot mode
+  //
+  SetPeiCacheMode ((const EFI_PEI_SERVICES **)PeiServices, FspHobList);
+
+  Status = PeiServicesGetBootMode (&BootMode);
+  ASSERT_EFI_ERROR (Status);
+
+  if (BootMode == BOOT_ON_S3_RESUME) {
+    DEBUG ((DEBUG_INFO, "Following BOOT_ON_S3_RESUME boot path.\n"));
+
+    Status = InstallS3Memory (PeiServices, BootMode, FspHobList);
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR (Status)) {
+      PeiServicesResetSystem ();
+    }
+
+    return EFI_SUCCESS;
+  }
+
+  Status = InstallEfiMemory (PeiServices, BootMode, FspHobList);
+  return Status;
+}
+
+/**
+  Process FSP HOB list
+
+  @param[in] FspHobList  Pointer to the HOB data structure produced by FSP.
+
+**/
+VOID
+ProcessFspHobList (
+  IN VOID  *FspHobList
+  )
+{
+  EFI_PEI_HOB_POINTERS  FspHob;
+
+  FspHob.Raw = FspHobList;
+
+  //
+  // Add all the HOBs from FSP binary to FSP wrapper
+  //
+  while (!END_OF_HOB_LIST (FspHob)) {
+    if (FspHob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
+      //
+      // Skip FSP binary creates PcdDataBaseHobGuid
+      //
+      if (!CompareGuid (&FspHob.Guid->Name, &gPcdDataBaseHobGuid)) {
+        BuildGuidDataHob (
+          &FspHob.Guid->Name,
+          GET_GUID_HOB_DATA (FspHob),
+          GET_GUID_HOB_DATA_SIZE (FspHob)
+          );
+      }
+    }
+
+    FspHob.Raw = GET_NEXT_HOB (FspHob);
+  }
+}
+
+/**
+  Post FSP-S HOB process (not Memory Resource Descriptor).
+
+  @param[in] FspHobList  Pointer to the HOB data structure produced by FSP.
+
+  @return If platform process the FSP hob list successfully.
+**/
+EFI_STATUS
+EFIAPI
+PostFspsHobProcess (
+  IN VOID  *FspHobList
+  )
+{
+  //
+  // PostFspsHobProcess () will be called in both FSP API and Dispatch modes to
+  // align the same behavior and support a variety of boot loader implementations.
+  // Boot loader provided library function is recommended to support both API and
+  // Dispatch modes by checking PcdFspModeSelection.
+  //
+  if (PcdGet8 (PcdFspModeSelection) == 1) {
+    //
+    // Only in FSP API mode the wrapper has to build hobs basing on FSP output data.
+    // In this case FspHobList cannot be NULL.
+    //
+    ASSERT (FspHobList != NULL);
+    ProcessFspHobList (FspHobList);
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetAvailableMemoryRanges (
+  IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE  *MemoryMap,
+  IN OUT UINT8                                  *NumRanges,
+  IN VOID                                       *FspHobList
+  )
+{
+  EFI_PEI_HOB_POINTERS  Hob;
+
+  DEBUG ((DEBUG_INFO, "GetAvailableMemoryRanges++\n"));
+  if ((*NumRanges) < MAX_RANGES) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *NumRanges = 0;
+
+  // Get Pointer to HOB
+  Hob.Raw = (UINT8 *)(UINTN)FspHobList;
+  ASSERT (Hob.Raw != NULL);
+  while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) {
+    if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY)) {
+      MemoryMap[*NumRanges].PhysicalAddress =  Hob.ResourceDescriptor->PhysicalStart;
+      MemoryMap[*NumRanges].CpuAddress      =  Hob.ResourceDescriptor->PhysicalStart;
+      MemoryMap[*NumRanges].RangeLength     =  Hob.ResourceDescriptor->ResourceLength;
+      MemoryMap[*NumRanges].Type            =  DualChannelDdrReservedMemory;
+      (*NumRanges)++;
+      DEBUG ((
+        DEBUG_INFO,
+        " GetAvailableMemoryRanges Base:0x%016lX, Size: 0x%016lX\n", \
+        Hob.ResourceDescriptor->PhysicalStart, \
+        Hob.ResourceDescriptor->ResourceLength
+        ));
+    }
+
+    Hob.Raw = GET_NEXT_HOB (Hob);
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetReservedMemoryRanges (
+  IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE  *MemoryMap,
+  IN OUT UINT8                                  *NumRanges,
+  IN VOID                                       *FspHobList
+  )
+{
+  EFI_PEI_HOB_POINTERS  Hob;
+
+  DEBUG ((DEBUG_INFO, "GetReservedMemoryRanges\n"));
+  if ((*NumRanges) < MAX_RANGES) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *NumRanges = 0;
+
+  // Get Pointer to HOB
+  Hob.Raw = (UINT8 *)(UINTN)FspHobList;
+  ASSERT (Hob.Raw != NULL);
+  while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) {
+    if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)) {
+      MemoryMap[*NumRanges].PhysicalAddress =  Hob.ResourceDescriptor->PhysicalStart;
+      MemoryMap[*NumRanges].CpuAddress      =  Hob.ResourceDescriptor->PhysicalStart;
+      MemoryMap[*NumRanges].RangeLength     =  Hob.ResourceDescriptor->ResourceLength;
+      MemoryMap[*NumRanges].Type            =  DualChannelDdrReservedMemory;
+      (*NumRanges)++;
+      DEBUG ((
+        DEBUG_INFO,
+        " GetReservedMemoryRanges Base:0x%016lX, Size: 0x%016lX\n", \
+        Hob.ResourceDescriptor->PhysicalStart, \
+        Hob.ResourceDescriptor->ResourceLength
+        ));
+    }
+
+    Hob.Raw = GET_NEXT_HOB (Hob);
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PreFspmHobProcess (
+  IN VOID  *FspHobList
+  )
+{
+  EFI_PEI_HOB_POINTERS  Hob;
+  UINT64                FspMemorySize;
+  EFI_PHYSICAL_ADDRESS  FspMemoryBase;
+  BOOLEAN               FoundFspMemHob;
+  UINT64                SpaceAfterFSPReservedMemory = 0;
+
+  FspMemorySize  = 0;
+  FspMemoryBase  = 0;
+  FoundFspMemHob = FALSE;
+
+  //
+  // Parse the hob list from fsp
+  // Report all the resource hob except the memory between 1M and 4G
+  //
+  Hob.Raw = (UINT8 *)(UINTN)FspHobList;
+  DEBUG ((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList));
+
+  // In HOBs returned by FSP-M, there is an unintended memory region overlap:
+  // e.g.:
+  // 0x00000000 - 0x80000000 Empty Memory
+  // 0x80000000 - 0xFFFFFFFF Reserved
+  // ......
+  // 0x7F000000 - 0x80000000 Taken by FSP
+  // Since AMD's current FSP implementation doesn't FIX empty memory size, so we do it here.
+
+  // Firstly we pick up FSP Memory information.
+  while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) {
+    if (  (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G
+       && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB)
+       && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)
+       && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobGuid)))
+    {
+      FoundFspMemHob = TRUE;
+      FspMemoryBase  = Hob.ResourceDescriptor->PhysicalStart;
+      FspMemorySize  = Hob.ResourceDescriptor->ResourceLength;
+      DEBUG ((DEBUG_INFO, "Find fsp mem hob, base 0x%llx, len 0x%llx\n", FspMemoryBase, FspMemorySize));
+      FSP_MEMORY_REGION_HOB  *FspRegion = BuildGuidHob (&gFspReservedMemoryResourceHobGuid, sizeof (FSP_MEMORY_REGION_HOB));
+      FspRegion->BeginAddress = Hob.ResourceDescriptor->PhysicalStart;
+      FspRegion->Length       = Hob.ResourceDescriptor->ResourceLength;
+    }
+
+    Hob.Raw = GET_NEXT_HOB (Hob);
+  }
+
+  Hob.Raw = (UINT8 *)(UINTN)FspHobList;
+
+  while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) {
+    DEBUG ((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType));
+    if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) ||
+        (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED))
+    {
+      DEBUG ((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute));
+      DEBUG ((DEBUG_INFO, "PhysicalStart: 0x%llx\n", Hob.ResourceDescriptor->PhysicalStart));
+      DEBUG ((DEBUG_INFO, "ResourceLength: 0x%llx\n", Hob.ResourceDescriptor->ResourceLength));
+      DEBUG ((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner));
+    }
+
+    if (  (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) // Found the low memory length below 4G
+       && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB))
+    {
+      // Now we fix the FSP memory overlap issue.
+      if (  (Hob.ResourceDescriptor->PhysicalStart < FspMemoryBase)
+         && (Hob.ResourceDescriptor->PhysicalStart+Hob.ResourceDescriptor->ResourceLength >= FspMemoryBase+FspMemorySize))
+      {
+        DEBUG ((DEBUG_ERROR, "Found overlap! Adjusting (%llx->%llx)\n", Hob.ResourceDescriptor->ResourceLength, Hob.ResourceDescriptor->ResourceLength-FspMemorySize));
+        SpaceAfterFSPReservedMemory             = (Hob.ResourceDescriptor->PhysicalStart+Hob.ResourceDescriptor->ResourceLength)-(FspMemoryBase+FspMemorySize);
+        Hob.ResourceDescriptor->ResourceLength -= (FspMemorySize+SpaceAfterFSPReservedMemory);
+      }
+
+      Hob.Raw = GET_NEXT_HOB (Hob);
+      continue;
+    }
+
+    if (  (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G
+       && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB)
+       && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)
+       && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobGuid)))
+    {
+      FoundFspMemHob = TRUE;
+      FspMemoryBase  = Hob.ResourceDescriptor->PhysicalStart;
+      FspMemorySize  = Hob.ResourceDescriptor->ResourceLength;
+      DEBUG ((DEBUG_INFO, "Find fsp mem hob, base 0x%llx, len 0x%llx\n", FspMemoryBase, FspMemorySize));
+    }
+
+    Hob.Raw = GET_NEXT_HOB (Hob);
+  }
+
+  if (!FoundFspMemHob) {
+    DEBUG ((DEBUG_INFO, "Didn't find the fsp used memory information.\n"));
+    // ASSERT(FALSE);
+  }
+
+  if (SpaceAfterFSPReservedMemory) {
+    DEBUG ((DEBUG_INFO, "Left some space after FSP. Creating space for them.\n"));
+  }
+
+  DEBUG ((DEBUG_INFO, "FspMemoryBase: 0x%x.\n", FspMemoryBase));
+  DEBUG ((DEBUG_INFO, "FspMemorySize: 0x%x.\n", FspMemorySize));
+  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
+    ),
+    FspMemoryBase,                            // MemoryBegin
+    FspMemorySize                             // MemoryLength
+    );
+  BuildMemoryAllocationHob (FspMemoryBase, FspMemorySize, EfiRuntimeServicesCode);
+
+  Hob.Raw = GetNextGuidHob (&gFspExportedInterfaceHobGuid, FspHobList);
+  FSP_EXPORTED_INTERFACE_HOB  *ExportedInterfaceHob = GET_GUID_HOB_DATA (Hob.Raw);
+  EFI_PEI_PPI_DESCRIPTOR      *FspProvidedPpiList   = AllocatePool (sizeof (EFI_PEI_PPI_DESCRIPTOR)*2);
+
+  if (FspProvidedPpiList != NULL) {
+    FspProvidedPpiList[0].Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI);
+    FspProvidedPpiList[0].Guid  = &gAmdPspFtpmPpiGuid;
+    FspProvidedPpiList[0].Ppi   = ExportedInterfaceHob->PspFtpmPpi;
+    FspProvidedPpiList[1].Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+    FspProvidedPpiList[1].Guid  = &gEfiPeiReset2PpiGuid;
+    FspProvidedPpiList[1].Ppi   = ExportedInterfaceHob->Reset2Ppi;
+  }
+
+  PeiServicesInstallPpi (FspProvidedPpiList);
+
+  Hob.Raw = GetNextGuidHob (&gAmdPspApobHobGuid, FspHobList);
+  APOBLIB_INFO  *ApobHob = GET_GUID_HOB_DATA (Hob.Raw);
+
+  if (ApobHob->Supported) {
+    DEBUG ((DEBUG_INFO, "FSP-M Wrapper: Reserving APOB region %p+%x\n", (UINTN)ApobHob->ApobAddr, ApobHob->ApobSize));
+    BuildMemoryAllocationHob (ApobHob->ApobAddr, ApobHob->ApobSize, EfiACPIMemoryNVS);
+  }
+
+  return EFI_SUCCESS;
+}
+
+VOID
+MtrrLibInitializeMtrrMask (
+  OUT UINT64  *MtrrValidBitsMask,
+  OUT UINT64  *MtrrValidAddressMask
+  );
+
+EFI_STATUS
+EFIAPI
+SetPeiCacheMode (
+  IN  CONST EFI_PEI_SERVICES  **PeiServices,
+  IN  VOID                    *FspHobList
+  )
+{
+  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,
+    FspHobList
+    );
+
+  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 (0xC0010010ul);
+    MsrData |= BIT22;
+    AsmWriteMsr64 (0xC0010010ul, MsrData);
+  }
+
+  for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {
+    if (MtrrSetting.Variables.Mtrr[Index].Base == 0) {
+      break;
+    }
+
+    DEBUG ((DEBUG_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 (0xC0010010ul, (AsmReadMsr64 (0xC0010010ul) | (1 << 19)));
+  MtrrSetAllMtrrs (&MtrrSetting);
+  AsmWriteMsr64 (0xC0010010ul, (AsmReadMsr64 (0xC0010010ul) & (~(1 << 19))));
+  //
+  // Dump MTRR Setting
+  //
+  MtrrDebugPrintAllMtrrs ();
+
+  return Status;
+}
+
+EFI_STATUS
+GetMemorySize (
+  IN  CONST EFI_PEI_SERVICES  **PeiServices,
+  OUT UINT64                  *LowMemoryLength,
+  OUT UINT64                  *HighMemoryLength,
+  OUT UINT64                  *GraphicMemoryBase OPTIONAL,
+  OUT UINT64                  *GraphicMemoryLength OPTIONAL,
+  IN VOID                     *FspHobList
+  )
+{
+  EFI_PEI_HOB_POINTERS  Hob;
+  EFI_PEI_HOB_POINTERS  FspHob;
+
+  *HighMemoryLength = 0;
+  *LowMemoryLength  = 0x100000;
+  // We don't support getting UMA information from FSP hob for now.
+  if ((GraphicMemoryBase != NULL) || (GraphicMemoryLength != NULL)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  // Get HOB Data
+  Hob.Raw    = (UINT8 *)(UINTN)FspHobList;
+  FspHob.Raw = NULL;
+  ASSERT (Hob.Raw != NULL);
+  while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) {
+    if (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobGuid)) {
+      FspHob.Raw = Hob.Raw;
+    }
+
+    if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+      if (Hob.ResourceDescriptor->PhysicalStart < SIZE_4GB) {
+        if (LowMemoryLength != NULL) {
+          *LowMemoryLength = Hob.ResourceDescriptor->ResourceLength;
+        }
+      } else if (Hob.ResourceDescriptor->PhysicalStart >= SIZE_4GB) {
+        if (HighMemoryLength != NULL) {
+          *HighMemoryLength = Hob.ResourceDescriptor->ResourceLength;
+        }
+      }
+    }
+
+    Hob.Raw = GET_NEXT_HOB (Hob);
+  }
+
+  if ((FspHob.Raw != NULL) && (*LowMemoryLength == FspHob.ResourceDescriptor->PhysicalStart)) {
+    // FSP should also be cached.
+    *LowMemoryLength += FspHob.ResourceDescriptor->ResourceLength;
+    DEBUG ((DEBUG_INFO, "Patching cache region for FSP area!\n"));
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/MemoryInstall.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/MemoryInstall.h
new file mode 100644
index 0000000000..c9a58aea56
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/MemoryInstall.h
@@ -0,0 +1,171 @@
+/** @file
+  Implements MemoryInstall.h
+  Framework PEIM to initialize memory on an DDR2 SDRAM Memory Controller.
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  Copyright (c) 2013 - 2016 Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MRC_WRAPPER_H_
+#define MRC_WRAPPER_H_
+
+//
+// Maximum number of memory ranges supported by the memory controller
+//
+#define MAX_RANGES  16
+
+//
+// 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.
+//
+
+EFI_STATUS
+InstallEfiMemory (
+  IN      EFI_PEI_SERVICES  **PeiServices,
+  IN      EFI_BOOT_MODE     BootMode,
+  IN      VOID              *FspHobList
+  );
+
+EFI_STATUS
+InstallS3Memory (
+  IN      EFI_PEI_SERVICES  **PeiServices,
+  IN      EFI_BOOT_MODE     BootMode,
+  IN      VOID              *FspHobList
+  );
+
+EFI_STATUS
+GetMemoryMap (
+  IN     EFI_PEI_SERVICES                       **PeiServices,
+  IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE  *MemoryMap,
+  IN OUT UINT8                                  *NumRanges,
+  IN      VOID                                  *FspHobList
+  );
+
+EFI_STATUS
+GetPlatformMemorySize (
+  IN      EFI_PEI_SERVICES  **PeiServices,
+  IN      EFI_BOOT_MODE     BootMode,
+  IN OUT  UINT64            *MemorySize
+  );
+
+EFI_STATUS
+PreFspmHobProcess (
+  IN VOID  *FspHobList
+  );
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
new file mode 100644
index 0000000000..8bc2681836
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
@@ -0,0 +1,121 @@
+## @file
+#  Sample to provide FSP wrapper hob process related function.
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiFspWrapperHobProcessLibSample
+  FILE_GUID                      = 864693E2-EDE8-4DF8-8871-38C0BAA157EB
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = FspWrapperHobProcessLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+  FspWrapperHobProcessLibSample.c
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  PcAtChipsetPkg/PcAtChipsetPkg.dec
+  ChachaniBoardPkg/Project.dec
+  VanGoghCommonPkg/AmdCommonPkg.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  HobLib
+  DebugLib
+  FspWrapperPlatformLib
+  PeiServicesLib
+  PeiServicesTablePointerLib
+  PrintLib
+  PcdLib
+  ReportStatusCodeLib
+  IoLib
+  PeimEntryPoint
+  MemoryAllocationLib
+  MtrrLib
+  PciExpressLib
+
+[Pcd]
+  gIntelFsp2WrapperTokenSpaceGuid.PcdPeiMinMemSize          ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdPeiRecoveryMinMemSize  ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection       ## CONSUMES
+  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
+  gPlatformPkgTokenSpaceGuid.PcdBootState
+  gEfiAmdAgesaModulePkgTokenSpaceGuid.PcdAmdFabricResourceDefaultSizePtr
+[Guids]
+  gFspReservedMemoryResourceHobGuid                       ## CONSUMES ## HOB
+  gEfiMemoryTypeInformationGuid                           ## CONSUMES ## GUID
+  gPcdDataBaseHobGuid                                     ## CONSUMES ## HOB
+  gEfiAcpiVariableGuid                          # ALWAYS_CONSUMED L"AcpiGlobalVariab"
+  gEfiSmmPeiSmramMemoryReserveGuid              # ALWAYS_PRODUCED  Hob: GUID_EXTENSION
+  gAmdMemoryInfoHobGuid
+  gPlatformChargerPresentGuid
+  gAmdResourceSizeForEachRbGuid
+  gAmdFspMemoryUnder1MGuid
+  gFspExportedInterfaceHobGuid
+  gAmdPspApobHobGuid
+
+[Ppis]
+  gEfiPeiCapsulePpiGuid                                   ## CONSUMES
+  gEfiPeiStallPpiGuid
+  gEfiPeiMasterBootModePpiGuid
+  gEfiPeiMemoryDiscoveredPpiGuid
+  gEfiPeiBootInRecoveryModePpiGuid
+  gAmdMemoryInfoHobPpiGuid
+  gEfiPeiReadOnlyVariable2PpiGuid
+  gPeiSmmControlPpiGuid
+  gPeiPostScriptTablePpiGuid
+  gEfiEndOfPeiSignalPpiGuid
+  gEfiPeiSmbus2PpiGuid
+  gEfiPeiReset2PpiGuid
+  gAmdPspFtpmPpiGuid
\ No newline at end of file
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Fsp.h b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Fsp.h
new file mode 100644
index 0000000000..09683fc11a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Fsp.h
@@ -0,0 +1,45 @@
+/** @file
+  Fsp related definitions
+
+  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FSP_H_
+#define FSP_H_
+
+//
+// Fv Header
+//
+#define FVH_FV_LENGTH_OFFSET         0x20
+#define FVH_SIGINATURE_OFFSET        0x28
+#define FVH_SIGINATURE_VALID_VALUE   0x4856465F   // valid signature:_FVH
+#define FVH_HEADER_LENGTH_OFFSET     0x30
+#define FVH_EXTHEADER_OFFSET_OFFSET  0x34
+#define FVH_EXTHEADER_SIZE_OFFSET    0x10
+
+//
+// Ffs Header
+//
+#define FSP_HEADER_SIGNATURE_OFFSET  0x1C
+#define FSP_HEADER_SIGNATURE         0x48505346    ; valid signature:FSPH
+#define FSP_HEADER_GUID_DWORD1       0x912740BE
+#define FSP_HEADER_GUID_DWORD2       0x47342284
+#define FSP_HEADER_GUID_DWORD3       0xB08471B9
+#define FSP_HEADER_GUID_DWORD4       0x0C3F3527
+#define FFS_HEADER_SIZE_VALUE        0x18
+
+//
+// Section Header
+//
+#define SECTION_HEADER_TYPE_OFFSET     0x03
+#define RAW_SECTION_HEADER_SIZE_VALUE  0x04
+
+//
+// Fsp Header
+//
+#define FSP_HEADER_IMAGEBASE_OFFSET    0x1C
+#define FSP_HEADER_TEMPRAMINIT_OFFSET  0x30
+
+#endif
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
new file mode 100644
index 0000000000..54f363e59d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
@@ -0,0 +1,129 @@
+/** @file
+  Sample to provide FSP wrapper platform sec related function.
+
+  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/SecPerformance.h>
+
+#include <Library/LocalApicLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+
+/**
+  This interface conveys state information out of the Security (SEC) phase into PEI.
+
+  @param[in]     PeiServices               Pointer to the PEI Services Table.
+  @param[in,out] StructureSize             Pointer to the variable describing size of the input buffer.
+  @param[out]    PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+  @retval EFI_SUCCESS           The data was successfully returned.
+  @retval EFI_BUFFER_TOO_SMALL  The buffer was too small.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformation (
+  IN CONST EFI_PEI_SERVICES                  **PeiServices,
+  IN OUT   UINT64                            *StructureSize,
+  OUT   EFI_SEC_PLATFORM_INFORMATION_RECORD  *PlatformInformationRecord
+  );
+
+/**
+  This interface conveys performance information out of the Security (SEC) phase into PEI.
+
+  This service is published by the SEC phase. The SEC phase handoff has an optional
+  EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the
+  PEI Foundation. As such, if the platform supports collecting performance data in SEC,
+  this information is encapsulated into the data structure abstracted by this service.
+  This information is collected for the boot-strap processor (BSP) on IA-32.
+
+  @param[in]  PeiServices  The pointer to the PEI Services Table.
+  @param[in]  This         The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI.
+  @param[out] Performance  The pointer to performance data collected in SEC phase.
+
+  @retval EFI_SUCCESS  The data was successfully returned.
+
+**/
+EFI_STATUS
+EFIAPI
+SecGetPerformance (
+  IN CONST EFI_PEI_SERVICES          **PeiServices,
+  IN       PEI_SEC_PERFORMANCE_PPI   *This,
+  OUT      FIRMWARE_SEC_PERFORMANCE  *Performance
+  );
+
+PEI_SEC_PERFORMANCE_PPI  mSecPerformancePpi = {
+  SecGetPerformance
+};
+
+EFI_PEI_PPI_DESCRIPTOR  mPeiSecPlatformPpi[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI,
+    &gTopOfTemporaryRamPpiGuid,
+    NULL // To be patched later.
+  },
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+    &gPeiSecPerformancePpiGuid,
+    &mSecPerformancePpi
+  },
+};
+
+/**
+  A developer supplied function to perform platform specific operations.
+
+  It's a developer supplied function to perform any operations appropriate to a
+  given platform. It's invoked just before passing control to PEI core by SEC
+  core. Platform developer may modify the SecCoreData passed to PEI Core.
+  It returns a platform specific PPI list that platform wishes to pass to PEI core.
+  The Generic SEC core module will merge this list to join the final list passed to
+  PEI core.
+
+  @param[in,out] SecCoreData           The same parameter as passing to PEI core. It
+                                       could be overridden by this function.
+
+  @return The platform specific PPI list to be passed to PEI core or
+          NULL if there is no need of such platform specific PPI list.
+
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+EFIAPI
+SecPlatformMain (
+  IN OUT   EFI_SEC_PEI_HAND_OFF  *SecCoreData
+  )
+{
+  EFI_PEI_PPI_DESCRIPTOR  *PpiList;
+
+  DEBUG ((DEBUG_INFO, "SecPlatformMain\n"));
+
+  DEBUG ((DEBUG_INFO, "BootFirmwareVolumeBase - 0x%x\n", SecCoreData->BootFirmwareVolumeBase));
+  DEBUG ((DEBUG_INFO, "BootFirmwareVolumeSize - 0x%x\n", SecCoreData->BootFirmwareVolumeSize));
+  DEBUG ((DEBUG_INFO, "TemporaryRamBase       - 0x%x\n", SecCoreData->TemporaryRamBase));
+  DEBUG ((DEBUG_INFO, "TemporaryRamSize       - 0x%x\n", SecCoreData->TemporaryRamSize));
+  DEBUG ((DEBUG_INFO, "PeiTemporaryRamBase    - 0x%x\n", SecCoreData->PeiTemporaryRamBase));
+  DEBUG ((DEBUG_INFO, "PeiTemporaryRamSize    - 0x%x\n", SecCoreData->PeiTemporaryRamSize));
+  DEBUG ((DEBUG_INFO, "StackBase              - 0x%x\n", SecCoreData->StackBase));
+  DEBUG ((DEBUG_INFO, "StackSize              - 0x%x\n", SecCoreData->StackSize));
+
+  InitializeApicTimer (0, (UINT32)-1, TRUE, 5);
+
+  //
+  // Use middle of Heap as temp buffer, it will be copied by caller.
+  // Do not use Stack, because it will cause wrong calculation on stack by PeiCore
+  //
+  PpiList = (VOID *)((UINTN)SecCoreData->PeiTemporaryRamBase + (UINTN)SecCoreData->PeiTemporaryRamSize/2);
+  CopyMem (PpiList, mPeiSecPlatformPpi, sizeof (mPeiSecPlatformPpi));
+
+  //
+  // Patch TopOfTemporaryRamPpi
+  //
+  PpiList[0].Ppi = (VOID *)((UINTN)SecCoreData->TemporaryRamBase + SecCoreData->TemporaryRamSize);
+
+  return PpiList;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
new file mode 100644
index 0000000000..cf443aa267
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
@@ -0,0 +1,130 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;  PeiCoreEntry.nasm
+;
+; Abstract:
+;
+;   Find and call SecStartup
+;
+;------------------------------------------------------------------------------
+
+SECTION .text
+
+extern ASM_PFX(SecStartup)
+extern ASM_PFX(PlatformInit)
+
+global ASM_PFX(CallPeiCoreEntryPoint)
+ASM_PFX(CallPeiCoreEntryPoint):
+  ;
+  ; Obtain the hob list pointer
+  ;
+  mov     eax, [esp+4]
+  ;
+  ; Obtain the stack information
+  ;   ECX: start of range
+  ;   EDX: end of range
+  ;
+  mov     ecx, [esp+8]
+  mov     edx, [esp+0xC]
+
+  ;
+  ; Platform init
+  ;
+  pushad
+  push edx
+  push ecx
+  push eax
+  call ASM_PFX(PlatformInit)
+  pop  eax
+  pop  eax
+  pop  eax
+  popad
+
+  ;
+  ; Set stack top pointer
+  ;
+  mov     esp, edx
+
+  ;
+  ; Push the hob list pointer
+  ;
+  push    eax
+
+  ;
+  ; Save the value
+  ;   ECX: start of range
+  ;   EDX: end of range
+  ;
+  mov     ebp, esp
+  push    ecx
+  push    edx
+
+  ;
+  ; Push processor count to stack first, then BIST status (AP then BSP)
+  ;
+  mov     eax, 1
+  cpuid
+  shr     ebx, 16
+  and     ebx, 0xFF
+  cmp     bl, 1
+  jae     PushProcessorCount
+
+  ;
+  ; Some processors report 0 logical processors.  Effectively 0 = 1.
+  ; So we fix up the processor count
+  ;
+  inc     ebx
+
+PushProcessorCount:
+  push    ebx
+
+  ;
+  ; We need to implement a long-term solution for BIST capture.  For now, we just copy BSP BIST
+  ; for all processor threads
+  ;
+  xor     ecx, ecx
+  mov     cl, bl
+PushBist:
+  movd    eax, mm0
+  push    eax
+  loop    PushBist
+
+  ; Save Time-Stamp Counter
+  movd eax, mm5
+  push eax
+
+  movd eax, mm6
+  push eax
+
+  ;
+  ; Pass entry point of the PEI core
+  ;
+  mov     edi, 0xFFFFFFE0
+  push    DWORD [edi]
+
+  ;
+  ; Pass BFV into the PEI Core
+  ;
+  mov     edi, 0xFFFFFFFC
+  push    DWORD [edi]
+
+  ;
+  ; Pass stack size into the PEI Core
+  ;
+  mov     ecx, [ebp - 4]
+  mov     edx, [ebp - 8]
+  push    ecx       ; RamBase
+
+  sub     edx, ecx
+  push    edx       ; RamSize
+
+  ;
+  ; Pass Control into the PEI Core
+  ;
+  call ASM_PFX(SecStartup)
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
new file mode 100644
index 0000000000..b506212bfa
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
@@ -0,0 +1,335 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;  SecEntry.asm
+;
+; Abstract:
+;
+;  This is the code that goes from real-mode to protected mode.
+;  It consumes the reset vector, calls TempRamInit API from FSP binary.
+;
+;------------------------------------------------------------------------------
+
+#include "Fsp.h"
+
+SECTION .text
+
+extern   ASM_PFX(CallPeiCoreEntryPoint)
+extern   ASM_PFX(FsptUpdDataPtr)
+
+; Pcds
+extern   ASM_PFX(PcdGet32 (PcdFsptBaseAddress))
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    _ModuleEntryPoint
+;
+; Input:        None
+;
+; Output:       None
+;
+; Destroys:     Assume all registers
+;
+; Description:
+;
+;   Transition to non-paged flat-model protected mode from a
+;   hard-coded GDT that provides exactly two descriptors.
+;   This is a bare bones transition to protected mode only
+;   used for a while in PEI and possibly DXE.
+;
+;   After enabling protected mode, a far jump is executed to
+;   transfer to PEI using the newly loaded GDT.
+;
+; Return:       None
+;
+;  MMX Usage:
+;              MM0 = BIST State
+;              MM5 = Save time-stamp counter value high32bit
+;              MM6 = Save time-stamp counter value low32bit.
+;
+;----------------------------------------------------------------------------
+
+BITS 16
+align 4
+global ASM_PFX(ModuleEntryPoint)
+ASM_PFX(ModuleEntryPoint):
+  fninit                                ; clear any pending Floating point exceptions
+  ;
+  ; Store the BIST value in mm0
+  ;
+  movd    mm0, eax
+
+  ;
+  ; Save time-stamp counter value
+  ; rdtsc load 64bit time-stamp counter to EDX:EAX
+  ;
+  rdtsc
+  movd    mm5, edx
+  movd    mm6, eax
+
+  ;
+  ; Load the GDT table in GdtDesc
+  ;
+  mov     esi,  GdtDesc
+  DB      66h
+  lgdt    [cs:si]
+
+  ;
+  ; Transition to 16 bit protected mode
+  ;
+  mov     eax, cr0                   ; Get control register 0
+  or      eax, 00000003h             ; Set PE bit (bit #0) & MP bit (bit #1)
+  mov     cr0, eax                   ; Activate protected mode
+
+  mov     eax, cr4                   ; Get control register 4
+  or      eax, 00000600h             ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
+  mov     cr4, eax
+
+  ;
+  ; Now we're in 16 bit protected mode
+  ; Set up the selectors for 32 bit protected mode entry
+  ;
+  mov     ax, SYS_DATA_SEL
+  mov     ds, ax
+  mov     es, ax
+  mov     fs, ax
+  mov     gs, ax
+  mov     ss, ax
+
+  ;
+  ; Transition to Flat 32 bit protected mode
+  ; The jump to a far pointer causes the transition to 32 bit mode
+  ;
+  mov esi, ProtectedModeEntryLinearAddress
+  jmp   dword far  [cs:si]
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    ProtectedModeEntryPoint
+;
+; Input:        None
+;
+; Output:       None
+;
+; Destroys:     Assume all registers
+;
+; Description:
+;
+; This function handles:
+;   Call two basic APIs from FSP binary
+;   Initializes stack with some early data (BIST, PEI entry, etc)
+;
+; Return:       None
+;
+;----------------------------------------------------------------------------
+
+BITS 32
+align 4
+ProtectedModeEntryPoint:
+
+  ; Find the fsp info header
+  mov  edi, [ASM_PFX(PcdGet32 (PcdFsptBaseAddress))]
+
+  mov  eax, dword [edi + FVH_SIGINATURE_OFFSET]
+  cmp  eax, FVH_SIGINATURE_VALID_VALUE
+  jnz  FspHeaderNotFound
+
+  xor  eax, eax
+  mov  ax, word [edi + FVH_EXTHEADER_OFFSET_OFFSET]
+  cmp  ax, 0
+  jnz  FspFvExtHeaderExist
+
+  xor  eax, eax
+  mov  ax, word [edi + FVH_HEADER_LENGTH_OFFSET]   ; Bypass Fv Header
+  add  edi, eax
+  jmp  FspCheckFfsHeader
+
+FspFvExtHeaderExist:
+  add  edi, eax
+  mov  eax, dword [edi + FVH_EXTHEADER_SIZE_OFFSET]  ; Bypass Ext Fv Header
+  add  edi, eax
+
+  ; Round up to 8 byte alignment
+  mov  eax, edi
+  and  al,  07h
+  jz   FspCheckFfsHeader
+
+  and  edi, 0FFFFFFF8h
+  add  edi, 08h
+
+FspCheckFfsHeader:
+  ; Check the ffs guid
+  mov  eax, dword [edi]
+  cmp  eax, FSP_HEADER_GUID_DWORD1
+  jnz  FspHeaderNotFound
+
+  mov  eax, dword [edi + 4]
+  cmp  eax, FSP_HEADER_GUID_DWORD2
+  jnz  FspHeaderNotFound
+
+  mov  eax, dword [edi + 8]
+  cmp  eax, FSP_HEADER_GUID_DWORD3
+  jnz  FspHeaderNotFound
+
+  mov  eax, dword [edi + 0Ch]
+  cmp  eax, FSP_HEADER_GUID_DWORD4
+  jnz  FspHeaderNotFound
+
+  add  edi, FFS_HEADER_SIZE_VALUE       ; Bypass the ffs header
+
+  ; Check the section type as raw section
+  mov  al, byte [edi + SECTION_HEADER_TYPE_OFFSET]
+  cmp  al, 019h
+  jnz FspHeaderNotFound
+
+  add  edi, RAW_SECTION_HEADER_SIZE_VALUE ; Bypass the section header
+  jmp FspHeaderFound
+
+FspHeaderNotFound:
+  jmp  $
+
+FspHeaderFound:
+  ; Get the fsp TempRamInit Api address
+  mov eax, dword [edi + FSP_HEADER_IMAGEBASE_OFFSET]
+  add eax, dword [edi + FSP_HEADER_TEMPRAMINIT_OFFSET]
+
+  ; Setup the hardcode stack
+  mov esp, TempRamInitStack
+
+  ; Call the fsp TempRamInit Api
+  jmp eax
+
+TempRamInitDone:
+  cmp eax, 8000000Eh      ;Check if EFI_NOT_FOUND returned. Error code for Microcode Update not found.
+  je  CallSecFspInit      ;If microcode not found, don't hang, but continue.
+
+  cmp eax, 0              ;Check if EFI_SUCCESS returned.
+  jnz FspApiFailed
+
+  ;   ECX: start of range
+  ;   EDX: end of range
+CallSecFspInit:
+  xor     eax, eax
+  mov     esp, edx
+
+  ; Align the stack at DWORD
+  add  esp,  3
+  and  esp, 0FFFFFFFCh
+
+  push    edx
+  push    ecx
+  push    eax ; zero - no hob list yet
+  call    ASM_PFX(CallPeiCoreEntryPoint)
+
+FspApiFailed:
+  jmp $
+
+align 10h
+TempRamInitStack:
+    DD  TempRamInitDone
+    DD  ASM_PFX(FsptUpdDataPtr); TempRamInitParams
+
+;
+; ROM-based Global-Descriptor Table for the Tiano PEI Phase
+;
+align 16
+global  ASM_PFX(BootGdtTable)
+
+;
+; GDT[0]: 0x00: Null entry, never used.
+;
+NULL_SEL            EQU $ - GDT_BASE    ; Selector [0]
+GDT_BASE:
+ASM_PFX(BootGdtTable):
+                    DD  0
+                    DD  0
+;
+; Linear data segment descriptor
+;
+LINEAR_SEL          EQU $ - GDT_BASE    ; Selector [0x8]
+    DW  0FFFFh                          ; limit 0xFFFFF
+    DW  0                               ; base 0
+    DB  0
+    DB  092h                            ; present, ring 0, data, expand-up, writable
+    DB  0CFh                            ; page-granular, 32-bit
+    DB  0
+;
+; Linear code segment descriptor
+;
+LINEAR_CODE_SEL     EQU $ - GDT_BASE    ; Selector [0x10]
+    DW  0FFFFh                          ; limit 0xFFFFF
+    DW  0                               ; base 0
+    DB  0
+    DB  09Bh                            ; present, ring 0, data, expand-up, not-writable
+    DB  0CFh                            ; page-granular, 32-bit
+    DB  0
+;
+; System data segment descriptor
+;
+SYS_DATA_SEL        EQU $ - GDT_BASE    ; Selector [0x18]
+    DW  0FFFFh                          ; limit 0xFFFFF
+    DW  0                               ; base 0
+    DB  0
+    DB  093h                            ; present, ring 0, data, expand-up, not-writable
+    DB  0CFh                            ; page-granular, 32-bit
+    DB  0
+
+;
+; System code segment descriptor
+;
+SYS_CODE_SEL        EQU $ - GDT_BASE    ; Selector [0x20]
+    DW  0FFFFh                          ; limit 0xFFFFF
+    DW  0                               ; base 0
+    DB  0
+    DB  09Ah                            ; present, ring 0, data, expand-up, writable
+    DB  0CFh                            ; page-granular, 32-bit
+    DB  0
+;
+; Spare segment descriptor
+;
+SYS16_CODE_SEL      EQU $ - GDT_BASE    ; Selector [0x28]
+    DW  0FFFFh                          ; limit 0xFFFFF
+    DW  0                               ; base 0
+    DB  0Eh                             ; Changed from F000 to E000.
+    DB  09Bh                            ; present, ring 0, code, expand-up, writable
+    DB  00h                             ; byte-granular, 16-bit
+    DB  0
+;
+; Spare segment descriptor
+;
+SYS16_DATA_SEL      EQU $ - GDT_BASE    ; Selector [0x30]
+    DW  0FFFFh                          ; limit 0xFFFF
+    DW  0                               ; base 0
+    DB  0
+    DB  093h                            ; present, ring 0, data, expand-up, not-writable
+    DB  00h                             ; byte-granular, 16-bit
+    DB  0
+
+;
+; Spare segment descriptor
+;
+SPARE5_SEL          EQU $ - GDT_BASE    ; Selector [0x38]
+    DW  0                               ; limit 0
+    DW  0                               ; base 0
+    DB  0
+    DB  0                               ; present, ring 0, data, expand-up, writable
+    DB  0                               ; page-granular, 32-bit
+    DB  0
+GDT_SIZE            EQU $ - GDT_BASE    ; Size, in bytes
+
+;
+; GDT Descriptor
+;
+GdtDesc:                                ; GDT descriptor
+    DW  GDT_SIZE - 1                    ; GDT limit
+    DD  GDT_BASE                        ; GDT base address
+
+
+ProtectedModeEntryLinearAddress:
+ProtectedModeEntryLinear:
+  DD      ProtectedModeEntryPoint  ; Offset of our 32 bit code
+  DW      LINEAR_CODE_SEL
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/Stack.nasm b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/Stack.nasm
new file mode 100644
index 0000000000..48101131fa
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/Ia32/Stack.nasm
@@ -0,0 +1,73 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Abstract:
+;
+;   Switch the stack from temporary memory to permanent memory.
+;
+;------------------------------------------------------------------------------
+
+    SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; SecSwitchStack (
+;   UINT32   TemporaryMemoryBase,
+;   UINT32   PermanentMemoryBase
+;   );
+;------------------------------------------------------------------------------
+global ASM_PFX(SecSwitchStack)
+ASM_PFX(SecSwitchStack):
+    ;
+    ; Save four register: eax, ebx, ecx, edx
+    ;
+    push  eax
+    push  ebx
+    push  ecx
+    push  edx
+
+    ;
+    ; !!CAUTION!! this function address's is pushed into stack after
+    ; migration of whole temporary memory, so need save it to permanent
+    ; memory at first!
+    ;
+
+    mov   ebx, [esp + 20]          ; Save the first parameter
+    mov   ecx, [esp + 24]          ; Save the second parameter
+
+    ;
+    ; Save this function's return address into permanent memory at first.
+    ; Then, Fixup the esp point to permanent memory
+    ;
+    mov   eax, esp
+    sub   eax, ebx
+    add   eax, ecx
+    mov   edx, dword [esp]         ; copy pushed register's value to permanent memory
+    mov   dword [eax], edx
+    mov   edx, dword [esp + 4]
+    mov   dword [eax + 4], edx
+    mov   edx, dword [esp + 8]
+    mov   dword [eax + 8], edx
+    mov   edx, dword [esp + 12]
+    mov   dword [eax + 12], edx
+    mov   edx, dword [esp + 16]    ; Update this function's return address into permanent memory
+    mov   dword [eax + 16], edx
+    mov   esp, eax                 ; From now, esp is pointed to permanent memory
+
+    ;
+    ; Fixup the ebp point to permanent memory
+    ;
+    mov   eax, ebp
+    sub   eax, ebx
+    add   eax, ecx
+    mov   ebp, eax                 ; From now, ebp is pointed to permanent memory
+
+    pop   edx
+    pop   ecx
+    pop   ebx
+    pop   eax
+    ret
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/PlatformInit.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/PlatformInit.c
new file mode 100644
index 0000000000..237aeead51
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/PlatformInit.c
@@ -0,0 +1,38 @@
+/** @file
+  Sample to provide platform init function.
+
+  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/DebugLib.h>
+#include <Library/SerialPortLib.h>
+
+/**
+  Platform initialization.
+
+  @param[in] FspHobList   HobList produced by FSP.
+  @param[in] StartOfRange Start of temporary RAM.
+  @param[in] EndOfRange   End of temporary RAM.
+**/
+VOID
+EFIAPI
+PlatformInit (
+  IN VOID  *FspHobList,
+  IN VOID  *StartOfRange,
+  IN VOID  *EndOfRange
+  )
+{
+  //
+  // Platform initialization
+  // Enable Serial port here
+  //
+  SerialPortInitialize ();
+
+  DEBUG ((DEBUG_INFO, "PrintPeiCoreEntryPointParam in PlatformInit\n"));
+  DEBUG ((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList));
+  DEBUG ((DEBUG_INFO, "StartOfRange - 0x%x\n", StartOfRange));
+  DEBUG ((DEBUG_INFO, "EndOfRange - 0x%x\n", EndOfRange));
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
new file mode 100644
index 0000000000..ac417c8e59
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
@@ -0,0 +1,87 @@
+## @file
+#  Sample to provide FSP wrapper platform sec related function.
+#
+#  Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SecFspWrapperPlatformSecLibSample
+  FILE_GUID                      = 8F1AC44A-CE7E-4E29-95BB-92E321BB1573
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformSecLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources]
+  FspWrapperPlatformSecLibSample.c
+  SecRamInitData.c
+  SecPlatformInformation.c
+  SecGetPerformance.c
+  SecTempRamDone.c
+  PlatformInit.c
+  Fsp.h
+
+[Sources.IA32]
+  Ia32/SecEntry.nasm
+  Ia32/PeiCoreEntry.nasm
+  Ia32/Stack.nasm
+
+[Sources.X64]
+  X64/SecEntry.nasm
+  X64/PeiCoreEntry.nasm
+  X64/Stack.nasm
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+#                              this module.
+#
+################################################################################
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+
+[LibraryClasses]
+  LocalApicLib
+  SerialPortLib
+  DebugLib
+  BaseMemoryLib
+
+[Ppis]
+  gEfiSecPlatformInformationPpiGuid       ## CONSUMES
+  gPeiSecPerformancePpiGuid               ## CONSUMES
+  gTopOfTemporaryRamPpiGuid               ## PRODUCES
+
+[Pcd]
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFsptBaseAddress              ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress              ## CONSUMES
+
+[FixedPcd]
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress           ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize        ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFlashCodeCacheAddress        ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFlashCodeCacheSize           ## CONSUMES
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecGetPerformance.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecGetPerformance.c
new file mode 100644
index 0000000000..449a2d6e99
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecGetPerformance.c
@@ -0,0 +1,84 @@
+/** @file
+  Sample to provide SecGetPerformance function.
+
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SecPerformance.h>
+#include <Ppi/TopOfTemporaryRam.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+
+/**
+  This interface conveys performance information out of the Security (SEC) phase into PEI.
+
+  This service is published by the SEC phase. The SEC phase handoff has an optional
+  EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the
+  PEI Foundation. As such, if the platform supports collecting performance data in SEC,
+  this information is encapsulated into the data structure abstracted by this service.
+  This information is collected for the boot-strap processor (BSP) on IA-32.
+
+  @param[in]  PeiServices  The pointer to the PEI Services Table.
+  @param[in]  This         The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI.
+  @param[out] Performance  The pointer to performance data collected in SEC phase.
+
+  @retval EFI_SUCCESS  The data was successfully returned.
+
+**/
+EFI_STATUS
+EFIAPI
+SecGetPerformance (
+  IN CONST EFI_PEI_SERVICES          **PeiServices,
+  IN       PEI_SEC_PERFORMANCE_PPI   *This,
+  OUT      FIRMWARE_SEC_PERFORMANCE  *Performance
+  )
+{
+  UINT32      Size;
+  UINT32      Count;
+  UINT32      TopOfTemporaryRam;
+  UINT64      Ticker;
+  VOID        *TopOfTemporaryRamPpi;
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "SecGetPerformance\n"));
+
+  Status = (*PeiServices)->LocatePpi (
+                             PeiServices,
+                             &gTopOfTemporaryRamPpiGuid,
+                             0,
+                             NULL,
+                             (VOID **)&TopOfTemporaryRamPpi
+                             );
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // |--------------| <- TopOfTemporaryRam
+  // |Number of BSPs|
+  // |--------------|
+  // |     BIST     |
+  // |--------------|
+  // |     ....     |
+  // |--------------|
+  // |  TSC[63:32]  |
+  // |--------------|
+  // |  TSC[31:00]  |
+  // |--------------|
+  //
+  TopOfTemporaryRam  = (UINT32)(UINTN)TopOfTemporaryRamPpi - sizeof (UINT32);
+  TopOfTemporaryRam -= sizeof (UINT32) * 2;
+  Count              = *(UINT32 *)(UINTN)(TopOfTemporaryRam - sizeof (UINT32));
+  Size               = Count * sizeof (UINT64);
+
+  Ticker                = *(UINT64 *)(UINTN)(TopOfTemporaryRam - sizeof (UINT32) - Size - sizeof (UINT32) * 2);
+  Performance->ResetEnd = GetTimeInNanoSecond (Ticker);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecPlatformInformation.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecPlatformInformation.c
new file mode 100644
index 0000000000..b96f38432e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecPlatformInformation.c
@@ -0,0 +1,78 @@
+/** @file
+  Sample to provide SecPlatformInformation function.
+
+  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/TopOfTemporaryRam.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+/**
+  This interface conveys state information out of the Security (SEC) phase into PEI.
+
+  @param[in]     PeiServices               Pointer to the PEI Services Table.
+  @param[in,out] StructureSize             Pointer to the variable describing size of the input buffer.
+  @param[out]    PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+  @retval EFI_SUCCESS           The data was successfully returned.
+  @retval EFI_BUFFER_TOO_SMALL  The buffer was too small.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformation (
+  IN CONST EFI_PEI_SERVICES                  **PeiServices,
+  IN OUT   UINT64                            *StructureSize,
+  OUT   EFI_SEC_PLATFORM_INFORMATION_RECORD  *PlatformInformationRecord
+  )
+{
+  UINT32      *Bist;
+  UINT32      Size;
+  UINT32      Count;
+  UINT32      TopOfTemporaryRam;
+  VOID        *TopOfTemporaryRamPpi;
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "SecPlatformInformation\n"));
+
+  Status = (*PeiServices)->LocatePpi (
+                             PeiServices,
+                             &gTopOfTemporaryRamPpiGuid,
+                             0,
+                             NULL,
+                             (VOID **)&TopOfTemporaryRamPpi
+                             );
+  if (EFI_ERROR (Status)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // The entries of BIST information, together with the number of them,
+  // reside in the bottom of stack, left untouched by normal stack operation.
+  // This routine copies the BIST information to the buffer pointed by
+  // PlatformInformationRecord for output.
+  //
+  TopOfTemporaryRam  = (UINT32)(UINTN)TopOfTemporaryRamPpi - sizeof (UINT32);
+  TopOfTemporaryRam -= sizeof (UINT32) * 2;
+  Count              = *((UINT32 *)(UINTN)(TopOfTemporaryRam - sizeof (UINT32)));
+  Size               = Count * sizeof (IA32_HANDOFF_STATUS);
+
+  if ((*StructureSize) < (UINT64)Size) {
+    *StructureSize = Size;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *StructureSize = Size;
+  Bist           = (UINT32 *)(TopOfTemporaryRam - sizeof (UINT32) - Size);
+
+  CopyMem (PlatformInformationRecord, Bist, Size);
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c
new file mode 100644
index 0000000000..5e7f051bb6
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c
@@ -0,0 +1,63 @@
+/** @file
+  Sample to provide TempRamInitParams data.
+
+  Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/PcdLib.h>
+#include <FspEas.h>
+
+typedef struct {
+  EFI_PHYSICAL_ADDRESS    MicrocodeRegionBase;
+  UINT64                  MicrocodeRegionSize;
+  EFI_PHYSICAL_ADDRESS    CodeRegionBase;
+  UINT64                  CodeRegionSize;
+} FSPT_CORE_UPD;
+
+typedef struct {
+  FSP_UPD_HEADER    FspUpdHeader;
+  //
+  // If FSP spec version < 2.2, remove FSPT_ARCH_UPD structure.
+  // Else If FSP spec version >= 2.2 and FSP spec version < 2.4, use FSPT_ARCH_UPD structure.
+  // Else, use FSPT_ARCH2_UPD structure.
+  //
+  FSPT_ARCH2_UPD    FsptArchUpd;
+  FSPT_CORE_UPD     FsptCoreUpd;
+} FSPT_UPD_CORE_DATA;
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST FSPT_UPD_CORE_DATA  FsptUpdDataPtr = {
+  {
+    0x4450555F54505346,
+    //
+    // UPD header revision must be equal or greater than 2 when the structure is compliant with FSP spec 2.2.
+    //
+    0x02,
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+  },
+  //
+  // If FSP spec version < 2.2, remove FSPT_ARCH_UPD structure.
+  // Else If FSP spec version >= 2.2 and FSP spec version < 2.4, use FSPT_ARCH_UPD structure.
+  // Else, use FSPT_ARCH2_UPD structure.
+  //
+  {
+    0x02,
+    {
+      0x00, 0x00, 0x00
+    },
+    0x00000020,
+    0x00000000,
+    {
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    }
+  },
+  {
+    FixedPcdGet32 (PcdCpuMicrocodePatchAddress),
+    FixedPcdGet32 (PcdCpuMicrocodePatchRegionSize),
+    FixedPcdGet32 (PcdFlashCodeCacheAddress),
+    FixedPcdGet32 (PcdFlashCodeCacheSize),
+  }
+};
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecTempRamDone.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecTempRamDone.c
new file mode 100644
index 0000000000..fab488e668
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecTempRamDone.c
@@ -0,0 +1,43 @@
+/** @file
+  Sample to provide SecTemporaryRamDone function.
+
+  Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/FspWrapperPlatformLib.h>
+#include <Guid/FspHeaderFile.h>
+
+/**
+This interface disables temporary memory in SEC Phase.
+**/
+VOID
+EFIAPI
+SecPlatformDisableTemporaryMemory (
+  VOID
+  )
+{
+  EFI_STATUS       Status;
+  VOID             *TempRamExitParam;
+  FSP_INFO_HEADER  *FspHeader;
+
+  FspHeader = FspFindFspHeader (PcdGet32 (PcdFspmBaseAddress));
+  if (FspHeader == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "SecPlatformDisableTemporaryMemory enter\n"));
+
+  TempRamExitParam = UpdateTempRamExitParam ();
+  Status           = CallTempRamExit (TempRamExitParam);
+  DEBUG ((DEBUG_INFO, "TempRamExit status: 0x%x\n", Status));
+  ASSERT_EFI_ERROR (Status);
+
+  return;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
new file mode 100644
index 0000000000..548474ccbb
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
@@ -0,0 +1,149 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;  PeiCoreEntry.nasm
+;
+; Abstract:
+;
+;   Find and call SecStartup
+;
+;------------------------------------------------------------------------------
+
+SECTION .text
+
+%include    "PushPopRegsNasm.inc"
+
+extern ASM_PFX(SecStartup)
+extern ASM_PFX(PlatformInit)
+
+;
+; args 1:XMM, 2:REG, 3:IDX
+;
+%macro LXMMN        3
+            pextrq  %2, %1, (%3 & 3)
+            %endmacro
+
+;
+; args 1:YMM, 2:XMM, 3:IDX (0 - lower 128bits, 1 - upper 128bits)
+;
+%macro LYMMN        3
+            vextractf128  %2, %1, %3
+            %endmacro
+
+%macro LOAD_TS      1
+            LYMMN   ymm6, xmm5, 1
+            LXMMN   xmm5, %1, 1
+            %endmacro
+
+global ASM_PFX(CallPeiCoreEntryPoint)
+ASM_PFX(CallPeiCoreEntryPoint):
+  ;
+  ; Per X64 calling convention, make sure RSP is 16-byte aligned.
+  ;
+  mov     rax, rsp
+  and     rax, 0fh
+  sub     rsp, rax
+
+  ;
+  ; Platform init
+  ;
+  PUSHA_64
+  sub     rsp, 20h
+  call    ASM_PFX(PlatformInit)
+  add     rsp, 20h
+  POPA_64
+
+  ;
+  ; Set stack top pointer
+  ;
+  mov     rsp, r8
+
+  ;
+  ; Push the hob list pointer
+  ;
+  push    rcx
+
+  ;
+  ; RBP holds start of BFV passed from Vtf0. Save it to r10.
+  ;
+  mov     r10, rbp
+
+  ;
+  ; Save the value
+  ;   RDX: start of range
+  ;   r8: end of range
+  ;
+  mov     rbp, rsp
+  push    rdx
+  push    r8
+  mov     r14, rdx
+  mov     r15, r8
+
+  ;
+  ; Push processor count to stack first, then BIST status (AP then BSP)
+  ;
+  mov     eax, 1
+  cpuid
+  shr     ebx, 16
+  and     ebx, 0000000FFh
+  cmp     bl, 1
+  jae     PushProcessorCount
+
+  ;
+  ; Some processors report 0 logical processors.  Effectively 0 = 1.
+  ; So we fix up the processor count
+  ;
+  inc     ebx
+
+PushProcessorCount:
+  sub     rsp, 4
+  mov     rdi, rsp
+  mov     DWORD [rdi], ebx
+
+  ;
+  ; We need to implement a long-term solution for BIST capture.  For now, we just copy BSP BIST
+  ; for all processor threads
+  ;
+  xor     ecx, ecx
+  mov     cl, bl
+PushBist:
+  sub     rsp, 4
+  mov     rdi, rsp
+  movd    eax, mm0
+  mov     DWORD [rdi], eax
+  loop    PushBist
+
+  ; Save Time-Stamp Counter
+  LOAD_TS rax
+  push    rax
+
+  ;
+  ; Pass entry point of the PEI core
+  ;
+  mov     rdi, 0FFFFFFE0h
+  mov     edi, DWORD [rdi]
+  mov     r9, rdi
+
+  ;
+  ; Pass BFV into the PEI Core
+  ;
+  mov     r8, r10
+
+  ;
+  ; Pass stack size into the PEI Core
+  ;
+  mov     rcx, r15  ; Start of TempRam
+  mov     rdx, r14  ; End of TempRam
+
+  sub     rcx, rdx  ; Size of TempRam
+
+  ;
+  ; Pass Control into the PEI Core
+  ;
+  sub     rsp, 20h
+  call ASM_PFX(SecStartup)
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/SecEntry.nasm b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/SecEntry.nasm
new file mode 100644
index 0000000000..4025b4157c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/SecEntry.nasm
@@ -0,0 +1,173 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+;  SecEntry.asm
+;
+; Abstract:
+;
+;  This is the code that calls TempRamInit API from FSP binary and passes
+;  control into PEI core.
+;
+;------------------------------------------------------------------------------
+
+#include "Fsp.h"
+
+IA32_CR4_OSFXSR           equ        200h
+IA32_CR4_OSXMMEXCPT       equ        400h
+IA32_CR0_MP               equ        2h
+
+IA32_CPUID_SSE2           equ        02000000h
+IA32_CPUID_SSE2_B         equ        26
+
+SECTION .text
+
+extern   ASM_PFX(CallPeiCoreEntryPoint)
+extern   ASM_PFX(FsptUpdDataPtr)
+
+; Pcds
+extern   ASM_PFX(PcdGet32 (PcdFsptBaseAddress))
+
+;----------------------------------------------------------------------------
+;
+; Procedure:    _ModuleEntryPoint
+;
+; Input:        None
+;
+; Output:       None
+;
+; Destroys:     Assume all registers
+;
+; Description:
+;
+;  Call TempRamInit API from FSP binary. After TempRamInit done, pass
+;  control into PEI core.
+;
+; Return:       None
+;
+;  MMX Usage:
+;              MM0 = BIST State
+;
+;----------------------------------------------------------------------------
+
+BITS 64
+align 16
+global ASM_PFX(ModuleEntryPoint)
+ASM_PFX(ModuleEntryPoint):
+  fninit                                ; clear any pending Floating point exceptions
+  ;
+  ; Store the BIST value in mm0
+  ;
+  movd    mm0, eax
+
+  ; Find the fsp info header
+  mov     rax, ASM_PFX(PcdGet32 (PcdFsptBaseAddress))
+  mov     edi, [eax]
+
+  mov     eax, dword [edi + FVH_SIGINATURE_OFFSET]
+  cmp     eax, FVH_SIGINATURE_VALID_VALUE
+  jnz     FspHeaderNotFound
+
+  xor     eax, eax
+  mov     ax, word [edi + FVH_EXTHEADER_OFFSET_OFFSET]
+  cmp     ax, 0
+  jnz     FspFvExtHeaderExist
+
+  xor     eax, eax
+  mov     ax, word [edi + FVH_HEADER_LENGTH_OFFSET]     ; Bypass Fv Header
+  add     edi, eax
+  jmp     FspCheckFfsHeader
+
+FspFvExtHeaderExist:
+  add     edi, eax
+  mov     eax, dword [edi + FVH_EXTHEADER_SIZE_OFFSET]  ; Bypass Ext Fv Header
+  add     edi, eax
+
+  ; Round up to 8 byte alignment
+  mov     eax, edi
+  and     al,  07h
+  jz      FspCheckFfsHeader
+
+  and     edi, 0FFFFFFF8h
+  add     edi, 08h
+
+FspCheckFfsHeader:
+  ; Check the ffs guid
+  mov     eax, dword [edi]
+  cmp     eax, FSP_HEADER_GUID_DWORD1
+  jnz     FspHeaderNotFound
+
+  mov     eax, dword [edi + 4]
+  cmp     eax, FSP_HEADER_GUID_DWORD2
+  jnz     FspHeaderNotFound
+
+  mov     eax, dword [edi + 8]
+  cmp     eax, FSP_HEADER_GUID_DWORD3
+  jnz     FspHeaderNotFound
+
+  mov     eax, dword [edi + 0Ch]
+  cmp     eax, FSP_HEADER_GUID_DWORD4
+  jnz     FspHeaderNotFound
+
+  add     edi, FFS_HEADER_SIZE_VALUE         ; Bypass the ffs header
+
+  ; Check the section type as raw section
+  mov     al, byte [edi + SECTION_HEADER_TYPE_OFFSET]
+  cmp     al, 019h
+  jnz FspHeaderNotFound
+
+  add     edi, RAW_SECTION_HEADER_SIZE_VALUE ; Bypass the section header
+  jmp     FspHeaderFound
+
+FspHeaderNotFound:
+  jmp     $
+
+FspHeaderFound:
+  ; Get the fsp TempRamInit Api address
+  mov     eax, dword [edi + FSP_HEADER_IMAGEBASE_OFFSET]
+  add     eax, dword [edi + FSP_HEADER_TEMPRAMINIT_OFFSET]
+
+  ; Pass Fsp T Upd pointer as Input parameter
+  mov     rcx, ASM_PFX(FsptUpdDataPtr)
+
+  ; Setup the hardcode stack
+  mov     rsp, TempRamInitStack
+
+  ; Call the fsp TempRamInit Api
+  jmp     rax
+
+TempRamInitDone:
+  cmp     rax, 0800000000000000Eh ; Check if EFI_NOT_FOUND returned. Error code for Microcode Update not found.
+  je      CallSecFspInit          ; If microcode not found, don't hang, but continue.
+
+  cmp     rax, 0                  ; Check if EFI_SUCCESS returned.
+  jnz     FspApiFailed
+
+  ; RDX: start of range
+  ; R8: end of range
+CallSecFspInit:
+
+  mov     r8,  rdx
+  mov     rdx, rcx
+  xor     ecx, ecx ; zero - no Hob List Yet
+  mov     rsp, r8
+
+  ;
+  ; Per X64 calling convention, make sure RSP is 16-byte aligned.
+  ;
+  mov     rax, rsp
+  and     rax, 0fh
+  sub     rsp, rax
+
+  call    ASM_PFX(CallPeiCoreEntryPoint)
+
+FspApiFailed:
+  jmp     $
+
+align 10h
+TempRamInitStack:
+    DQ  TempRamInitDone
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/Stack.nasm b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/Stack.nasm
new file mode 100644
index 0000000000..6feb38ce02
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/X64/Stack.nasm
@@ -0,0 +1,73 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Abstract:
+;
+;   Switch the stack from temporary memory to permanent memory.
+;
+;------------------------------------------------------------------------------
+
+    SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; SecSwitchStack (
+;   UINT32   TemporaryMemoryBase,
+;   UINT32   PermanentMemoryBase
+;   );
+;------------------------------------------------------------------------------
+global ASM_PFX(SecSwitchStack)
+ASM_PFX(SecSwitchStack):
+    ;
+    ; Save four register: rax, rbx, rcx, rdx
+    ;
+    push  rax
+    push  rbx
+    push  rcx
+    push  rdx
+
+    ;
+    ; !!CAUTION!! this function address's is pushed into stack after
+    ; migration of whole temporary memory, so need save it to permanent
+    ; memory at first!
+    ;
+
+    mov   rbx, rcx                 ; Save the first parameter
+    mov   rcx, rdx                 ; Save the second parameter
+
+    ;
+    ; Save this function's return address into permanent memory at first.
+    ; Then, Fixup the esp point to permanent memory
+    ;
+    mov   rax, rsp
+    sub   rax, rbx
+    add   rax, rcx
+    mov   rdx, qword [rsp]         ; copy pushed register's value to permanent memory
+    mov   qword [rax], rdx
+    mov   rdx, qword [rsp + 8]
+    mov   qword [rax + 8], rdx
+    mov   rdx, qword [rsp + 16]
+    mov   qword [rax + 16], rdx
+    mov   rdx, qword [rsp + 24]
+    mov   qword [rax + 24], rdx
+    mov   rdx, qword [rsp + 32]    ; Update this function's return address into permanent memory
+    mov   qword [rax + 32], rdx
+    mov   rsp, rax                 ; From now, rsp is pointed to permanent memory
+
+    ;
+    ; Fixup the rbp point to permanent memory
+    ;
+    mov   rax, rbp
+    sub   rax, rbx
+    add   rax, rcx
+    mov   rbp, rax                 ; From now, rbp is pointed to permanent memory
+
+    pop   rdx
+    pop   rcx
+    pop   rbx
+    pop   rax
+    ret
+
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.c
new file mode 100644
index 0000000000..87abe27c09
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.c
@@ -0,0 +1,152 @@
+/** @file
+  Implements PrepareForFspSmmDxe.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <FspsUpd.h>
+#include <MultiPhaseSiPhases.h>
+#include <FspSmmDataExchangeBuffer.h>
+#include <Pi/PiHob.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Protocol/MmCommunication2.h>
+
+#ifdef TPM_ENABLE
+#define TOTAL_DEPENDENCY_COUNT  2
+#else
+#define TOTAL_DEPENDENCY_COUNT  1// No TCG2.
+#endif
+
+STATIC FSPS_UPD *volatile                      FspsUpd;
+STATIC FSP_SMM_DATA_EXCHANGE_BUFFER *volatile  ExchangeBuffer;
+STATIC volatile UINTN                          DependencyCount = 0;
+
+extern EFI_GUID  gFspsUpdDataPointerAddressGuid;
+extern EFI_GUID  gExchangeBufferUpdateNotifyGuid;
+extern EFI_GUID  gFspSmmDependencyReadyProtocolGuid;
+
+STATIC
+EFI_STATUS
+CallFspAfterSmmConditionsMet (
+  VOID
+  )
+{
+  EFI_STATUS  Status = EFI_SUCCESS;
+  EFI_HANDLE  Handle = NULL;
+
+  gST->BootServices->InstallProtocolInterface (
+                       &Handle,
+                       &gFspSmmDependencyReadyProtocolGuid,
+                       EFI_NATIVE_INTERFACE,
+                       NULL
+                       );
+  // }
+  return Status;
+}
+
+VOID
+EFIAPI
+OnRequiredProtocolReady (
+  IN  EFI_EVENT  Event,
+  IN  VOID       *Context
+  )
+{
+  VOID  *Interface;
+
+  gBS->CloseEvent (Event);
+  gBS->LocateProtocol (Context, NULL, &Interface);
+  DEBUG ((DEBUG_INFO, "%a:located %g at %011p\n", __FILE__, Context, Interface));
+  if (CompareGuid (Context, &gEfiGlobalNvsAreaProtocolGuid)) {
+    ExchangeBuffer->NvsAreaProtocol = Interface;
+    DEBUG ((DEBUG_INFO, "%a:gEfiGlobalNvsAreaProtocolGuid\n", __FILE__));
+    DependencyCount++;
+    goto check_dependencies_count;
+  }
+
+  if (CompareGuid (Context, &gEfiTcg2ProtocolGuid)) {
+    ExchangeBuffer->EfiTcg2Protocol = Interface;
+    DEBUG ((DEBUG_INFO, "%a:gEfiTcg2ProtocolGuid\n", __FILE__));
+    DependencyCount++;
+    goto check_dependencies_count;
+  }
+
+check_dependencies_count:
+  if (DependencyCount == TOTAL_DEPENDENCY_COUNT) {
+    DEBUG ((DEBUG_INFO, "All Dependencies are ready!\n"));
+    CallFspAfterSmmConditionsMet ();
+  }
+}
+
+EFI_STATUS
+EFIAPI
+PrepareForFSPSmmDxeEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  VOID        *FspsUpdHob = GetFirstGuidHob (&gFspsUpdDataPointerAddressGuid);
+  VOID        *Registration;
+
+  if ( FspsUpdHob != NULL ) {
+    FspsUpd        = ((FSPS_UPD *)(UINTN)(*(UINT32 *)GET_GUID_HOB_DATA (FspsUpdHob)));
+    ExchangeBuffer = AllocateZeroPool (sizeof (FSP_SMM_DATA_EXCHANGE_BUFFER));
+    if ( ExchangeBuffer == NULL ) {
+      DEBUG ((DEBUG_ERROR, "Cannot Allocate memory for SMM data exchange!\n"));
+      return EFI_ABORTED;
+    }
+
+    FspsUpd->FspsConfig.smm_data_buffer_address = (UINT64)(UINTN)ExchangeBuffer;
+    DEBUG ((DEBUG_ERROR, "Exchange Buffer is at %011p\n", ExchangeBuffer));
+    // Create callbacks to acquire protocol base address.
+    Status = gBS->LocateProtocol (&gEfiGlobalNvsAreaProtocolGuid, NULL, &(ExchangeBuffer->NvsAreaProtocol));
+    if (EFI_ERROR (Status)) {
+      EfiNamedEventListen (
+        &gEfiGlobalNvsAreaProtocolGuid,
+        TPL_NOTIFY,
+        OnRequiredProtocolReady,
+        &gEfiGlobalNvsAreaProtocolGuid,
+        &Registration
+        );
+    } else {
+      DEBUG ((DEBUG_INFO, "%a:gEfiGlobalNvsAreaProtocolGuid is installed already\n", __FILE__));
+      DependencyCount++;
+    }
+
+    Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, &(ExchangeBuffer->EfiTcg2Protocol));
+    if (EFI_ERROR (Status)) {
+      EfiNamedEventListen (
+        &gEfiTcg2ProtocolGuid,
+        TPL_NOTIFY,
+        OnRequiredProtocolReady,
+        &gEfiTcg2ProtocolGuid,
+        &Registration
+        );
+    } else {
+      DEBUG ((DEBUG_INFO, "%a:gEfiTcg2ProtocolGuid is installed already\n", __FILE__));
+      DependencyCount++;
+    }
+
+    if (DependencyCount == 5) {
+      DEBUG ((DEBUG_INFO, "All Dependencies are ready!\n"));
+      CallFspAfterSmmConditionsMet ();
+    }
+  } else {
+    DEBUG ((DEBUG_ERROR, "Cannot locate FSP-S UPD!\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.inf
new file mode 100644
index 0000000000..03d6c9d668
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxe/PrepareForFspSmmDxe.inf
@@ -0,0 +1,57 @@
+## @file
+#  FSP SMM DXE INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PrepareForFspSmmDxe
+  FILE_GUID                      = 48FFA2F1-6F90-4009-8BA1-F6DDCF3F272D
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PrepareForFSPSmmDxeEntryPoint
+
+
+[Sources]
+  PrepareForFspSmmDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  AmdCommonPkg/AmdBct/AmdBctPkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  ChachaniBoardPkg/Project.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  MemoryAllocationLib
+  FspWrapperApiLib
+  DebugLib
+  BaseLib
+  UefiLib
+  HobLib
+
+[Protocols]
+  gEfiGlobalNvsAreaProtocolGuid
+  gEfiHiiDatabaseProtocolGuid
+  gEfiTcg2ProtocolGuid
+  gEfiVariableArchProtocolGuid
+  gEfiVariableWriteArchProtocolGuid
+  gPspFlashAccSmmCommReadyProtocolGuid
+  gFspSmmDependencyReadyProtocolGuid
+
+[Guids]
+  gFspsUpdDataPointerAddressGuid
+  gExchangeBufferUpdateNotifyGuid                   ## FOR SMI
+
+[Pcd]
+  gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInMemory # CONSUMES
+
+[Depex]
+  TRUE                  ## FOR SMM Communication
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.c b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.c
new file mode 100644
index 0000000000..05e5a0bd08
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.c
@@ -0,0 +1,86 @@
+/** @file
+  Implements PrepareForFspSmmDxeFsp.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <FspsUpd.h>
+#include <FspSmmDataExchangeBuffer.h>
+#include <Pi/PiHob.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SmmServicesTableLib.h>
+
+extern EFI_GUID  gExchangeBufferUpdateNotifyGuid;
+
+STATIC FSPS_UPD *volatile                      FspsUpd;
+STATIC FSP_SMM_DATA_EXCHANGE_BUFFER *volatile  ExchangeBuffer;
+STATIC EFI_HANDLE                              ExchangeBufferHandle;
+
+STATIC EFI_GUID  *MonitoredGuids[] = {
+  &gEfiGlobalNvsAreaProtocolGuid,
+  &gEfiTcg2ProtocolGuid
+};
+STATIC BOOLEAN   ProtocolInstalled[sizeof (MonitoredGuids)/sizeof (VOID *)];
+
+extern EFI_GUID  gFspsUpdDataPointerAddressGuid;
+
+EFI_STATUS
+EFIAPI
+DetectAndInstallNewProtocol (
+  VOID
+  )
+{
+  if ((ExchangeBuffer->NvsAreaProtocol != 0) && (ProtocolInstalled[0] == FALSE)) {
+    VOID  *Handle = NULL;
+    gBS->InstallMultipleProtocolInterfaces (
+           &Handle,
+           &gEfiGlobalNvsAreaProtocolGuid,
+           ExchangeBuffer->NvsAreaProtocol,
+           NULL
+           );
+    ProtocolInstalled[0] = TRUE;
+  }
+
+  if ((ExchangeBuffer->EfiTcg2Protocol != 0) && (ProtocolInstalled[4] == FALSE)) {
+    VOID  *Handle = NULL;
+    gBS->InstallMultipleProtocolInterfaces (
+           &Handle,
+           &gEfiTcg2ProtocolGuid,
+           ExchangeBuffer->EfiTcg2Protocol,
+           NULL
+           );
+    ProtocolInstalled[1] = TRUE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PrepareForFSPSmmDxeFspEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  VOID  *FspsUpdHob = GetFirstGuidHob (&gFspsUpdDataPointerAddressGuid);
+
+  if ( FspsUpdHob != NULL ) {
+    FspsUpd        = ((FSPS_UPD *)(UINTN)(*(UINT32 *)GET_GUID_HOB_DATA (FspsUpdHob)));
+    ExchangeBuffer = (FSP_SMM_DATA_EXCHANGE_BUFFER *)(UINTN)FspsUpd->FspsConfig.smm_data_buffer_address;
+    DEBUG ((DEBUG_ERROR, "Exchange Buffer is at %011p\n", ExchangeBuffer));
+    DetectAndInstallNewProtocol ();
+  } else {
+    DEBUG ((DEBUG_ERROR, "Cannot locate FSP-S UPD!\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.inf b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.inf
new file mode 100644
index 0000000000..19dd25b27f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForFspSmmDxeFsp/PrepareForFspSmmDxeFsp.inf
@@ -0,0 +1,49 @@
+#  FSP SMM DXE for FSP INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##************************************************************************
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PrepareForFspSmmDxeFsp
+  FILE_GUID                      = 6D4E6FB4-BA8D-4736-88A1-CC50EFFB2DC0
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PrepareForFSPSmmDxeFspEntryPoint
+
+
+[Sources]
+  PrepareForFspSmmDxeFsp.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  IntelFsp2Pkg/IntelFsp2Pkg.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+  ChachaniBoardPkg/Project.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  MemoryAllocationLib
+  DebugLib
+  HobLib
+
+[Protocols]
+  gEfiGlobalNvsAreaProtocolGuid
+  gEfiHiiDatabaseProtocolGuid
+  gEfiTcg2ProtocolGuid
+  gEfiTcgProtocolGuid
+  gEfiVariableArchProtocolGuid
+  gEfiVariableWriteArchProtocolGuid
+
+[Guids]
+  gFspsUpdDataPointerAddressGuid
+  gExchangeBufferUpdateNotifyGuid                   ## FOR SMI
+
+[Pcd]
+
+[Depex]
+  gFspSmmDependencyReadyProtocolGuid
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114607): https://edk2.groups.io/g/devel/message/114607
Mute This Topic: https://groups.io/mt/103975491/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (26 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 29/32] AMD/VanGoghBoard: Check in SmramSaveState module Zhai, MingXin (Duke) via groups.io
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial SmmCpuFeaturesLibCommon module. The CPU specific programming for
  PiSmmCpuDxeSmm module when STM support is not included.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../SmmCpuFeaturesLibCommon.c                 | 623 ++++++++++++++++++
 1 file changed, 623 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c
new file mode 100644
index 0000000000..f3615e2d9e
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c
@@ -0,0 +1,623 @@
+/** @file
+Implementation shared across all library instances.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+#include <Library/SmmCpuFeaturesLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MtrrLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Intel/Cpuid.h>
+#include <Register/Intel/SmramSaveStateMap.h>
+#include "CpuFeaturesLib.h"
+
+//
+// Machine Specific Registers (MSRs)
+//
+#define  SMM_FEATURES_LIB_IA32_MTRR_CAP            0x0FE
+#define  SMM_FEATURES_LIB_IA32_FEATURE_CONTROL     0x03A
+#define  SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE       0x1F2
+#define  SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK       0x1F3
+#define  SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE  0x0A0
+#define  SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK  0x0A1
+#define    EFI_MSR_SMRR_MASK                       0xFFFFF000
+#define    EFI_MSR_SMRR_PHYS_MASK_VALID            BIT11
+#define  SMM_FEATURES_LIB_SMM_FEATURE_CONTROL      0x4E0
+
+//
+// MSRs required for configuration of SMM Code Access Check
+//
+#define SMM_FEATURES_LIB_IA32_MCA_CAP  0x17D
+#define   SMM_CODE_ACCESS_CHK_BIT      BIT58
+
+extern UINT8  mSmmSaveStateRegisterLma;
+
+//
+// Set default value to assume SMRR is not supported
+//
+BOOLEAN  mSmrrSupported = FALSE;
+
+//
+// Set default value to assume MSR_SMM_FEATURE_CONTROL is not supported
+//
+BOOLEAN  mSmmFeatureControlSupported = FALSE;
+
+//
+// Set default value to assume IA-32 Architectural MSRs are used
+//
+UINT32  mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE;
+UINT32  mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK;
+
+//
+// Set default value to assume MTRRs need to be configured on each SMI
+//
+BOOLEAN  mNeedConfigureMtrrs = TRUE;
+
+//
+// Array for state of SMRR enable on all CPUs
+//
+BOOLEAN  *mSmrrEnabled;
+
+/**
+  Performs library initialization.
+
+  This initialization function contains common functionality shared betwen all
+  library instance constructors.
+
+**/
+VOID
+CpuFeaturesLibInitialization (
+  VOID
+  )
+{
+  UINT32  RegEax;
+  UINT32  RegEdx;
+  UINTN   FamilyId;
+  UINTN   ModelId;
+
+  //
+  // Retrieve CPU Family and Model
+  //
+  AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
+  FamilyId = (RegEax >> 8) & 0xf;
+  ModelId  = (RegEax >> 4) & 0xf;
+  if ((FamilyId == 0x06) || (FamilyId == 0x0f)) {
+    ModelId = ModelId | ((RegEax >> 12) & 0xf0);
+  }
+
+  //
+  // Check CPUID(CPUID_VERSION_INFO).EDX[12] for MTRR capability
+  //
+  if ((RegEdx & BIT12) != 0) {
+    //
+    // Check MTRR_CAP MSR bit 11 for SMRR support
+    //
+    if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MTRR_CAP) & BIT11) != 0) {
+      mSmrrSupported = TRUE;
+    }
+  }
+
+  //
+  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+  // Volume 3C, Section 35.3 MSRs in the Intel(R) Atom(TM) Processor Family
+  //
+  // If CPU Family/Model is 06_1CH, 06_26H, 06_27H, 06_35H or 06_36H, then
+  // SMRR Physical Base and SMM Physical Mask MSRs are not available.
+  //
+  if (FamilyId == 0x06) {
+    if ((ModelId == 0x1C) || (ModelId == 0x26) || (ModelId == 0x27) || (ModelId == 0x35) || (ModelId == 0x36)) {
+      mSmrrSupported = FALSE;
+    }
+  }
+
+  //
+  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+  // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
+  //
+  // If CPU Family/Model is 06_0F or 06_17, then use Intel(R) Core(TM) 2
+  // Processor Family MSRs
+  //
+  if (FamilyId == 0x06) {
+    if ((ModelId == 0x17) || (ModelId == 0x0f)) {
+      mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE;
+      mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK;
+    }
+  }
+
+  //
+  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+  // Volume 3C, Section 34.4.2 SMRAM Caching
+  //   An IA-32 processor does not automatically write back and invalidate its
+  //   caches before entering SMM or before exiting SMM. Because of this behavior,
+  //   care must be taken in the placement of the SMRAM in system memory and in
+  //   the caching of the SMRAM to prevent cache incoherence when switching back
+  //   and forth between SMM and protected mode operation.
+  //
+  // An IA-32 processor is a processor that does not support the Intel 64
+  // Architecture.  Support for the Intel 64 Architecture can be detected from
+  // CPUID(CPUID_EXTENDED_CPU_SIG).EDX[29]
+  //
+  // If an IA-32 processor is detected, then set mNeedConfigureMtrrs to TRUE,
+  // so caches are flushed on SMI entry and SMI exit, the interrupted code
+  // MTRRs are saved/restored, and MTRRs for SMM are loaded.
+  //
+  AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+  if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
+    AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
+    if ((RegEdx & BIT29) != 0) {
+      mNeedConfigureMtrrs = FALSE;
+    }
+  }
+
+  //
+  // Allocate array for state of SMRR enable on all CPUs
+  //
+  mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * GetCpuMaxLogicalProcessorNumber ());
+  ASSERT (mSmrrEnabled != NULL);
+}
+
+/**
+  Called during the very first SMI into System Management Mode to initialize
+  CPU features, including SMBASE, for the currently executing CPU.  Since this
+  is the first SMI, the SMRAM Save State Map is at the default address of
+  SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET.  The currently executing
+  CPU is specified by CpuIndex and CpuIndex can be used to access information
+  about the currently executing CPU in the ProcessorInfo array and the
+  HotPlugCpuData data structure.
+
+  @param[in] CpuIndex        The index of the CPU to initialize.  The value
+                             must be between 0 and the NumberOfCpus field in
+                             the System Management System Table (SMST).
+  @param[in] IsMonarch       TRUE if the CpuIndex is the index of the CPU that
+                             was elected as monarch during System Management
+                             Mode initialization.
+                             FALSE if the CpuIndex is not the index of the CPU
+                             that was elected as monarch during System
+                             Management Mode initialization.
+  @param[in] ProcessorInfo   Pointer to an array of EFI_PROCESSOR_INFORMATION
+                             structures.  ProcessorInfo[CpuIndex] contains the
+                             information for the currently executing CPU.
+  @param[in] CpuHotPlugData  Pointer to the CPU_HOT_PLUG_DATA structure that
+                             contains the ApidId and SmBase arrays.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesInitializeProcessor (
+  IN UINTN                      CpuIndex,
+  IN BOOLEAN                    IsMonarch,
+  IN EFI_PROCESSOR_INFORMATION  *ProcessorInfo,
+  IN CPU_HOT_PLUG_DATA          *CpuHotPlugData
+  )
+{
+  SMRAM_SAVE_STATE_MAP  *CpuState;
+  UINT64                FeatureControl;
+  UINT32                RegEax;
+  UINT32                RegEdx;
+  UINTN                 FamilyId;
+  UINTN                 ModelId;
+
+  //
+  // Configure SMBASE.
+  //
+  CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+  if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
+    CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
+  } else {
+    CpuState->x64.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
+  }
+
+  //
+  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+  // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
+  //
+  // If Intel(R) Core(TM) Core(TM) 2 Processor Family MSRs are being used, then
+  // make sure SMRR Enable(BIT3) of MSR_FEATURE_CONTROL MSR(0x3A) is set before
+  // accessing SMRR base/mask MSRs.  If Lock(BIT0) of MSR_FEATURE_CONTROL MSR(0x3A)
+  // is set, then the MSR is locked and can not be modified.
+  //
+  if (mSmrrSupported && (mSmrrPhysBaseMsr == SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE)) {
+    FeatureControl = AsmReadMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL);
+    if ((FeatureControl & BIT3) == 0) {
+      if ((FeatureControl & BIT0) == 0) {
+        AsmWriteMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL, FeatureControl | BIT3);
+      } else {
+        mSmrrSupported = FALSE;
+      }
+    }
+  }
+
+  //
+  // If SMRR is supported, then program SMRR base/mask MSRs.
+  // The EFI_MSR_SMRR_PHYS_MASK_VALID bit is not set until the first normal SMI.
+  // The code that initializes SMM environment is running in normal mode
+  // from SMRAM region.  If SMRR is enabled here, then the SMRAM region
+  // is protected and the normal mode code execution will fail.
+  //
+  if (mSmrrSupported) {
+    //
+    // SMRR size cannot be less than 4-KBytes
+    // SMRR size must be of length 2^n
+    // SMRR base alignment cannot be less than SMRR length
+    //
+    if ((CpuHotPlugData->SmrrSize < SIZE_4KB) ||
+        (CpuHotPlugData->SmrrSize != GetPowerOfTwo32 (CpuHotPlugData->SmrrSize)) ||
+        ((CpuHotPlugData->SmrrBase & ~(CpuHotPlugData->SmrrSize - 1)) != CpuHotPlugData->SmrrBase))
+    {
+      //
+      // Print message and halt if CPU is Monarch
+      //
+      if (IsMonarch) {
+        DEBUG ((DEBUG_ERROR, "SMM Base/Size does not meet alignment/size requirement!\n"));
+        CpuDeadLoop ();
+      }
+    } else {
+      AsmWriteMsr64 (mSmrrPhysBaseMsr, CpuHotPlugData->SmrrBase | MTRR_CACHE_WRITE_BACK);
+      AsmWriteMsr64 (mSmrrPhysMaskMsr, (~(CpuHotPlugData->SmrrSize - 1) & EFI_MSR_SMRR_MASK));
+      mSmrrEnabled[CpuIndex] = FALSE;
+    }
+  }
+
+  //
+  // Retrieve CPU Family and Model
+  //
+  AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
+  FamilyId = (RegEax >> 8) & 0xf;
+  ModelId  = (RegEax >> 4) & 0xf;
+  if ((FamilyId == 0x06) || (FamilyId == 0x0f)) {
+    ModelId = ModelId | ((RegEax >> 12) & 0xf0);
+  }
+
+  //
+  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+  // Volume 3C, Section 35.10.1 MSRs in 4th Generation Intel(R) Core(TM)
+  // Processor Family.
+  //
+  // If CPU Family/Model is 06_3C, 06_45, or 06_46 then use 4th Generation
+  // Intel(R) Core(TM) Processor Family MSRs.
+  //
+  if (FamilyId == 0x06) {
+    if ((ModelId == 0x3C) || (ModelId == 0x45) || (ModelId == 0x46) ||
+        (ModelId == 0x3D) || (ModelId == 0x47) || (ModelId == 0x4E) || (ModelId == 0x4F) ||
+        (ModelId == 0x3F) || (ModelId == 0x56) || (ModelId == 0x57) || (ModelId == 0x5C) ||
+        (ModelId == 0x8C))
+    {
+      //
+      // Check to see if the CPU supports the SMM Code Access Check feature
+      // Do not access this MSR unless the CPU supports the SmmRegFeatureControl
+      //
+      if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) != 0) {
+        mSmmFeatureControlSupported = TRUE;
+      }
+    }
+  }
+
+  //
+  //  Call internal worker function that completes the CPU initialization
+  //
+  FinishSmmCpuFeaturesInitializeProcessor ();
+}
+
+/**
+  This function updates the SMRAM save state on the currently executing CPU
+  to resume execution at a specific address after an RSM instruction.  This
+  function must evaluate the SMRAM save state to determine the execution mode
+  the RSM instruction resumes and update the resume execution address with
+  either NewInstructionPointer32 or NewInstructionPoint.  The auto HALT restart
+  flag in the SMRAM save state must always be cleared.  This function returns
+  the value of the instruction pointer from the SMRAM save state that was
+  replaced.  If this function returns 0, then the SMRAM save state was not
+  modified.
+
+  This function is called during the very first SMI on each CPU after
+  SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
+  to signal that the SMBASE of each CPU has been updated before the default
+  SMBASE address is used for the first SMI to the next CPU.
+
+  @param[in] CpuIndex                 The index of the CPU to hook.  The value
+                                      must be between 0 and the NumberOfCpus
+                                      field in the System Management System Table
+                                      (SMST).
+  @param[in] CpuState                 Pointer to SMRAM Save State Map for the
+                                      currently executing CPU.
+  @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
+                                      32-bit execution mode from 64-bit SMM.
+  @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
+                                      same execution mode as SMM.
+
+  @retval 0    This function did modify the SMRAM save state.
+  @retval > 0  The original instruction pointer value from the SMRAM save state
+               before it was replaced.
+**/
+UINT64
+EFIAPI
+SmmCpuFeaturesHookReturnFromSmm (
+  IN UINTN                 CpuIndex,
+  IN SMRAM_SAVE_STATE_MAP  *CpuState,
+  IN UINT64                NewInstructionPointer32,
+  IN UINT64                NewInstructionPointer
+  )
+{
+  return 0;
+}
+
+/**
+  Hook point in normal execution mode that allows the one CPU that was elected
+  as monarch during System Management Mode initialization to perform additional
+  initialization actions immediately after all of the CPUs have processed their
+  first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
+  into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesSmmRelocationComplete (
+  VOID
+  )
+{
+}
+
+/**
+  Determines if MTRR registers must be configured to set SMRAM cache-ability
+  when executing in System Management Mode.
+
+  @retval TRUE   MTRR registers must be configured to set SMRAM cache-ability.
+  @retval FALSE  MTRR registers do not need to be configured to set SMRAM
+                 cache-ability.
+**/
+BOOLEAN
+EFIAPI
+SmmCpuFeaturesNeedConfigureMtrrs (
+  VOID
+  )
+{
+  return mNeedConfigureMtrrs;
+}
+
+/**
+  Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
+  returns TRUE.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesDisableSmrr (
+  VOID
+  )
+{
+  if (mSmrrSupported && mNeedConfigureMtrrs) {
+    AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64 (mSmrrPhysMaskMsr) & ~EFI_MSR_SMRR_PHYS_MASK_VALID);
+  }
+}
+
+/**
+  Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
+  returns TRUE.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesReenableSmrr (
+  VOID
+  )
+{
+  if (mSmrrSupported && mNeedConfigureMtrrs) {
+    AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64 (mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
+  }
+}
+
+/**
+  Processor specific hook point each time a CPU enters System Management Mode.
+
+  @param[in] CpuIndex  The index of the CPU that has entered SMM.  The value
+                       must be between 0 and the NumberOfCpus field in the
+                       System Management System Table (SMST).
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesRendezvousEntry (
+  IN UINTN  CpuIndex
+  )
+{
+  //
+  // If SMRR is supported and this is the first normal SMI, then enable SMRR
+  //
+  if (mSmrrSupported && !mSmrrEnabled[CpuIndex]) {
+    AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64 (mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
+    mSmrrEnabled[CpuIndex] = TRUE;
+  }
+}
+
+/**
+  Processor specific hook point each time a CPU exits System Management Mode.
+
+  @param[in] CpuIndex  The index of the CPU that is exiting SMM.  The value must
+                       be between 0 and the NumberOfCpus field in the System
+                       Management System Table (SMST).
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesRendezvousExit (
+  IN UINTN  CpuIndex
+  )
+{
+}
+
+/**
+  Check to see if an SMM register is supported by a specified CPU.
+
+  @param[in] CpuIndex  The index of the CPU to check for SMM register support.
+                       The value must be between 0 and the NumberOfCpus field
+                       in the System Management System Table (SMST).
+  @param[in] RegName   Identifies the SMM register to check for support.
+
+  @retval TRUE   The SMM register specified by RegName is supported by the CPU
+                 specified by CpuIndex.
+  @retval FALSE  The SMM register specified by RegName is not supported by the
+                 CPU specified by CpuIndex.
+**/
+BOOLEAN
+EFIAPI
+SmmCpuFeaturesIsSmmRegisterSupported (
+  IN UINTN         CpuIndex,
+  IN SMM_REG_NAME  RegName
+  )
+{
+  if (mSmmFeatureControlSupported && (RegName == SmmRegFeatureControl)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Returns the current value of the SMM register for the specified CPU.
+  If the SMM register is not supported, then 0 is returned.
+
+  @param[in] CpuIndex  The index of the CPU to read the SMM register.  The
+                       value must be between 0 and the NumberOfCpus field in
+                       the System Management System Table (SMST).
+  @param[in] RegName   Identifies the SMM register to read.
+
+  @return  The value of the SMM register specified by RegName from the CPU
+           specified by CpuIndex.
+**/
+UINT64
+EFIAPI
+SmmCpuFeaturesGetSmmRegister (
+  IN UINTN         CpuIndex,
+  IN SMM_REG_NAME  RegName
+  )
+{
+  if (mSmmFeatureControlSupported && (RegName == SmmRegFeatureControl)) {
+    return AsmReadMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL);
+  }
+
+  return 0;
+}
+
+/**
+  Sets the value of an SMM register on a specified CPU.
+  If the SMM register is not supported, then no action is performed.
+
+  @param[in] CpuIndex  The index of the CPU to write the SMM register.  The
+                       value must be between 0 and the NumberOfCpus field in
+                       the System Management System Table (SMST).
+  @param[in] RegName   Identifies the SMM register to write.
+                       registers are read-only.
+  @param[in] Value     The value to write to the SMM register.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesSetSmmRegister (
+  IN UINTN         CpuIndex,
+  IN SMM_REG_NAME  RegName,
+  IN UINT64        Value
+  )
+{
+  if (mSmmFeatureControlSupported && (RegName == SmmRegFeatureControl)) {
+    AsmWriteMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL, Value);
+  }
+}
+
+/**
+  Read an SMM Save State register on the target processor.  If this function
+  returns EFI_UNSUPPORTED, then the caller is responsible for reading the
+  SMM Save Sate register.
+
+  @param[in]  CpuIndex  The index of the CPU to read the SMM Save State.  The
+                        value must be between 0 and the NumberOfCpus field in
+                        the System Management System Table (SMST).
+  @param[in]  Register  The SMM Save State register to read.
+  @param[in]  Width     The number of bytes to read from the CPU save state.
+  @param[out] Buffer    Upon return, this holds the CPU register value read
+                        from the save state.
+
+  @retval EFI_SUCCESS           The register was read from Save State.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_UNSUPPORTED       This function does not support reading Register.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuFeaturesReadSaveStateRegister (
+  IN  UINTN                        CpuIndex,
+  IN  EFI_SMM_SAVE_STATE_REGISTER  Register,
+  IN  UINTN                        Width,
+  OUT VOID                         *Buffer
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Writes an SMM Save State register on the target processor.  If this function
+  returns EFI_UNSUPPORTED, then the caller is responsible for writing the
+  SMM Save Sate register.
+
+  @param[in] CpuIndex  The index of the CPU to write the SMM Save State.  The
+                       value must be between 0 and the NumberOfCpus field in
+                       the System Management System Table (SMST).
+  @param[in] Register  The SMM Save State register to write.
+  @param[in] Width     The number of bytes to write to the CPU save state.
+  @param[in] Buffer    Upon entry, this holds the new CPU register value.
+
+  @retval EFI_SUCCESS           The register was written to Save State.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
+  @retval EFI_UNSUPPORTED       This function does not support writing Register.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuFeaturesWriteSaveStateRegister (
+  IN UINTN                        CpuIndex,
+  IN EFI_SMM_SAVE_STATE_REGISTER  Register,
+  IN UINTN                        Width,
+  IN CONST VOID                   *Buffer
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
+  notification is completely processed.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesCompleteSmmReadyToLock (
+  VOID
+  )
+{
+}
+
+/**
+  This API provides a method for a CPU to allocate a specific region for storing page tables.
+
+  This API can be called more once to allocate memory for page tables.
+
+  Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
+  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
+  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
+  returned.
+
+  This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.
+
+  @param  Pages                 The number of 4 KB pages to allocate.
+
+  @return A pointer to the allocated buffer for page tables.
+  @retval NULL      Fail to allocate a specific region for storing page tables,
+                    Or there is no preference on where the page tables are allocated in SMRAM.
+
+**/
+VOID *
+EFIAPI
+SmmCpuFeaturesAllocatePageTableMemory (
+  IN UINTN  Pages
+  )
+{
+  return NULL;
+}
--
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114603): https://edk2.groups.io/g/devel/message/114603
Mute This Topic: https://groups.io/mt/103975485/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 29/32] AMD/VanGoghBoard: Check in SmramSaveState module
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (27 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 30/32] AMD/VanGoghBoard: Check in EDK2 override files Zhai, MingXin (Duke) via groups.io
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial SmramSaveState module.
  This module provides services to access SMRAM Save State Map.

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>
---
 .../PiSmmCpuDxeSmm/SmramSaveState.c           | 706 ++++++++++++++++++
 1 file changed, 706 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
new file mode 100644
index 0000000000..ca63de9ba6
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
@@ -0,0 +1,706 @@
+/** @file
+Provides services to access SMRAM Save State Map
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiSmm.h>
+
+#include <Library/SmmCpuFeaturesLib.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/DebugLib.h>
+
+#include "PiSmmCpuDxeSmm.h"
+
+typedef struct {
+  UINT64    Signature;                                      // Offset 0x00
+  UINT16    Reserved1;                                      // Offset 0x08
+  UINT16    Reserved2;                                      // Offset 0x0A
+  UINT16    Reserved3;                                      // Offset 0x0C
+  UINT16    SmmCs;                                          // Offset 0x0E
+  UINT16    SmmDs;                                          // Offset 0x10
+  UINT16    SmmSs;                                          // Offset 0x12
+  UINT16    SmmOtherSegment;                                // Offset 0x14
+  UINT16    Reserved4;                                      // Offset 0x16
+  UINT64    Reserved5;                                      // Offset 0x18
+  UINT64    Reserved6;                                      // Offset 0x20
+  UINT64    Reserved7;                                      // Offset 0x28
+  UINT64    SmmGdtPtr;                                      // Offset 0x30
+  UINT32    SmmGdtSize;                                     // Offset 0x38
+  UINT32    Reserved8;                                      // Offset 0x3C
+  UINT64    Reserved9;                                      // Offset 0x40
+  UINT64    Reserved10;                                     // Offset 0x48
+  UINT16    Reserved11;                                     // Offset 0x50
+  UINT16    Reserved12;                                     // Offset 0x52
+  UINT32    Reserved13;                                     // Offset 0x54
+  UINT64    Reserved14;                                     // Offset 0x58
+} PROCESSOR_SMM_DESCRIPTOR;
+
+extern CONST PROCESSOR_SMM_DESCRIPTOR  gcPsd;
+
+//
+// EFER register LMA bit
+//
+#define LMA  BIT10
+
+///
+/// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
+///
+#define SMM_CPU_OFFSET(Field)  OFFSET_OF (SMRAM_SAVE_STATE_MAP, Field)
+
+///
+/// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_STATE_REGISTER_RANGE
+///
+#define SMM_REGISTER_RANGE(Start, End)  { Start, End, End - Start + 1 }
+
+///
+/// Structure used to describe a range of registers
+///
+typedef struct {
+  EFI_SMM_SAVE_STATE_REGISTER    Start;
+  EFI_SMM_SAVE_STATE_REGISTER    End;
+  UINTN                          Length;
+} CPU_SMM_SAVE_STATE_REGISTER_RANGE;
+
+///
+/// Structure used to build a lookup table to retrieve the widths and offsets
+/// associated with each supported EFI_SMM_SAVE_STATE_REGISTER value
+///
+
+#define SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX   1
+#define SMM_SAVE_STATE_REGISTER_IOMISC_INDEX     2
+#define SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX  3
+#define SMM_SAVE_STATE_REGISTER_MAX_INDEX        4
+
+typedef struct {
+  UINT8      Width32;
+  UINT8      Width64;
+  UINT16     Offset32;
+  UINT16     Offset64Lo;
+  UINT16     Offset64Hi;
+  BOOLEAN    Writeable;
+} CPU_SMM_SAVE_STATE_LOOKUP_ENTRY;
+
+///
+/// Structure used to build a lookup table for the IOMisc width information
+///
+typedef struct {
+  UINT8                          Width;
+  EFI_SMM_SAVE_STATE_IO_WIDTH    IoWidth;
+} CPU_SMM_SAVE_STATE_IO_WIDTH;
+
+///
+/// Variables from SMI Handler
+///
+X86_ASSEMBLY_PATCH_LABEL  gPatchSmbase;
+X86_ASSEMBLY_PATCH_LABEL  gPatchSmiStack;
+X86_ASSEMBLY_PATCH_LABEL  gPatchSmiCr3;
+extern volatile UINT8     gcSmiHandlerTemplate[];
+extern CONST UINT16       gcSmiHandlerSize;
+
+//
+// Variables used by SMI Handler
+//
+IA32_DESCRIPTOR  gSmiHandlerIdtr;
+
+///
+/// Table used by GetRegisterIndex() to convert an EFI_SMM_SAVE_STATE_REGISTER
+/// value to an index into a table of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
+///
+CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE  mSmmCpuRegisterRanges[] = {
+  SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_GDTBASE, EFI_SMM_SAVE_STATE_REGISTER_LDTINFO),
+  SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_ES,      EFI_SMM_SAVE_STATE_REGISTER_RIP),
+  SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_RFLAGS,  EFI_SMM_SAVE_STATE_REGISTER_CR4),
+  { (EFI_SMM_SAVE_STATE_REGISTER)0,                        (EFI_SMM_SAVE_STATE_REGISTER)0,      0}
+};
+
+///
+/// Lookup table used to retrieve the widths and offsets associated with each
+/// supported EFI_SMM_SAVE_STATE_REGISTER value
+///
+CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY  mSmmCpuWidthOffset[] = {
+  { 0, 0, 0,                            0,                                    0,                                    FALSE },  //  Reserved
+
+  //
+  // CPU Save State registers defined in PI SMM CPU Protocol.
+  //
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64.GdtrBaseLoDword), SMM_CPU_OFFSET (x64.GdtrBaseHiDword), FALSE },  //  EFI_SMM_SAVE_STATE_REGISTER_GDTBASE  = 4
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64.IdtrBaseLoDword), SMM_CPU_OFFSET (x64.IdtrBaseHiDword), FALSE },  //  EFI_SMM_SAVE_STATE_REGISTER_IDTBASE  = 5
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64.LdtrBaseLoDword), SMM_CPU_OFFSET (x64.LdtrBaseHiDword), FALSE },  //  EFI_SMM_SAVE_STATE_REGISTER_LDTBASE  = 6
+  { 0, 0, 0,                            SMM_CPU_OFFSET (x64.GdtrLimit),       0,                                    FALSE },  //  EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT = 7
+  { 0, 0, 0,                            SMM_CPU_OFFSET (x64.IdtrLimit),       0,                                    FALSE },  //  EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT = 8
+  { 0, 0, 0,                            SMM_CPU_OFFSET (x64.LdtrLimit),       0,                                    FALSE },  //  EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT = 9
+  { 0, 0, 0,                            0,                                    0,                                    FALSE },  //  EFI_SMM_SAVE_STATE_REGISTER_LDTINFO  = 10
+
+  { 4, 4, SMM_CPU_OFFSET (x86._ES),     SMM_CPU_OFFSET (x64._ES),             0,                                    FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_ES       = 20
+  { 4, 4, SMM_CPU_OFFSET (x86._CS),     SMM_CPU_OFFSET (x64._CS),             0,                                    FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_CS       = 21
+  { 4, 4, SMM_CPU_OFFSET (x86._SS),     SMM_CPU_OFFSET (x64._SS),             0,                                    FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_SS       = 22
+  { 4, 4, SMM_CPU_OFFSET (x86._DS),     SMM_CPU_OFFSET (x64._DS),             0,                                    FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_DS       = 23
+  { 4, 4, SMM_CPU_OFFSET (x86._FS),     SMM_CPU_OFFSET (x64._FS),             0,                                    FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_FS       = 24
+  { 4, 4, SMM_CPU_OFFSET (x86._GS),     SMM_CPU_OFFSET (x64._GS),             0,                                    FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_GS       = 25
+  { 0, 4, 0,                            SMM_CPU_OFFSET (x64.LdtrSelector),    0,                                    FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL = 26
+  { 4, 4, SMM_CPU_OFFSET (x86._TR),     SMM_CPU_OFFSET (x64.TrSelector),      0,                                    FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_TR_SEL   = 27
+  { 4, 8, SMM_CPU_OFFSET (x86._DR7),    SMM_CPU_OFFSET (x64._DR7),            SMM_CPU_OFFSET (x64._DR7)    + 4,     FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_DR7      = 28
+  { 4, 8, SMM_CPU_OFFSET (x86._DR6),    SMM_CPU_OFFSET (x64._DR6),            SMM_CPU_OFFSET (x64._DR6)    + 4,     FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_DR6      = 29
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64._R8),             SMM_CPU_OFFSET (x64._R8)     + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R8       = 30
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64._R9),             SMM_CPU_OFFSET (x64._R9)     + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R9       = 31
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64._R10),            SMM_CPU_OFFSET (x64._R10)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R10      = 32
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64._R11),            SMM_CPU_OFFSET (x64._R11)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R11      = 33
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64._R12),            SMM_CPU_OFFSET (x64._R12)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R12      = 34
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64._R13),            SMM_CPU_OFFSET (x64._R13)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R13      = 35
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64._R14),            SMM_CPU_OFFSET (x64._R14)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R14      = 36
+  { 0, 8, 0,                            SMM_CPU_OFFSET (x64._R15),            SMM_CPU_OFFSET (x64._R15)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_R15      = 37
+  { 4, 8, SMM_CPU_OFFSET (x86._EAX),    SMM_CPU_OFFSET (x64._RAX),            SMM_CPU_OFFSET (x64._RAX)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RAX      = 38
+  { 4, 8, SMM_CPU_OFFSET (x86._EBX),    SMM_CPU_OFFSET (x64._RBX),            SMM_CPU_OFFSET (x64._RBX)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RBX      = 39
+  { 4, 8, SMM_CPU_OFFSET (x86._ECX),    SMM_CPU_OFFSET (x64._RCX),            SMM_CPU_OFFSET (x64._RCX)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RCX      = 40
+  { 4, 8, SMM_CPU_OFFSET (x86._EDX),    SMM_CPU_OFFSET (x64._RDX),            SMM_CPU_OFFSET (x64._RDX)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RDX      = 41
+  { 4, 8, SMM_CPU_OFFSET (x86._ESP),    SMM_CPU_OFFSET (x64._RSP),            SMM_CPU_OFFSET (x64._RSP)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RSP      = 42
+  { 4, 8, SMM_CPU_OFFSET (x86._EBP),    SMM_CPU_OFFSET (x64._RBP),            SMM_CPU_OFFSET (x64._RBP)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RBP      = 43
+  { 4, 8, SMM_CPU_OFFSET (x86._ESI),    SMM_CPU_OFFSET (x64._RSI),            SMM_CPU_OFFSET (x64._RSI)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RSI      = 44
+  { 4, 8, SMM_CPU_OFFSET (x86._EDI),    SMM_CPU_OFFSET (x64._RDI),            SMM_CPU_OFFSET (x64._RDI)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RDI      = 45
+  { 4, 8, SMM_CPU_OFFSET (x86._EIP),    SMM_CPU_OFFSET (x64._RIP),            SMM_CPU_OFFSET (x64._RIP)    + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RIP      = 46
+
+  { 4, 8, SMM_CPU_OFFSET (x86._EFLAGS), SMM_CPU_OFFSET (x64._RFLAGS),         SMM_CPU_OFFSET (x64._RFLAGS) + 4,     TRUE  }, //  EFI_SMM_SAVE_STATE_REGISTER_RFLAGS   = 51
+  { 4, 8, SMM_CPU_OFFSET (x86._CR0),    SMM_CPU_OFFSET (x64._CR0),            SMM_CPU_OFFSET (x64._CR0)    + 4,     FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_CR0      = 52
+  { 4, 8, SMM_CPU_OFFSET (x86._CR3),    SMM_CPU_OFFSET (x64._CR3),            SMM_CPU_OFFSET (x64._CR3)    + 4,     FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_CR3      = 53
+  { 0, 4, 0,                            SMM_CPU_OFFSET (x64._CR4),            0,                                    FALSE }, //  EFI_SMM_SAVE_STATE_REGISTER_CR4      = 54
+};
+
+///
+/// Lookup table for the IOMisc width information
+///
+CONST CPU_SMM_SAVE_STATE_IO_WIDTH  mSmmCpuIoWidth[] = {
+  { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // Undefined           = 0
+  { 1, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // SMM_IO_LENGTH_BYTE  = 1
+  { 2, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT16 },  // SMM_IO_LENGTH_WORD  = 2
+  { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // Undefined           = 3
+  { 4, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32 },  // SMM_IO_LENGTH_DWORD = 4
+  { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // Undefined           = 5
+  { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  },  // Undefined           = 6
+  { 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8  }   // Undefined           = 7
+};
+
+///
+/// Lookup table for the IOMisc type information
+///
+CONST EFI_SMM_SAVE_STATE_IO_TYPE  mSmmCpuIoType[] = {
+  EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT,     // SMM_IO_TYPE_OUT_DX        = 0
+  EFI_SMM_SAVE_STATE_IO_TYPE_INPUT,      // SMM_IO_TYPE_IN_DX         = 1
+  EFI_SMM_SAVE_STATE_IO_TYPE_STRING,     // SMM_IO_TYPE_OUTS          = 2
+  EFI_SMM_SAVE_STATE_IO_TYPE_STRING,     // SMM_IO_TYPE_INS           = 3
+  (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 4
+  (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 5
+  EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_OUTS      = 6
+  EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_INS       = 7
+  EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT,     // SMM_IO_TYPE_OUT_IMMEDIATE = 8
+  EFI_SMM_SAVE_STATE_IO_TYPE_INPUT,      // SMM_IO_TYPE_OUT_IMMEDIATE = 9
+  (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 10
+  (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 11
+  (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 12
+  (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 13
+  (EFI_SMM_SAVE_STATE_IO_TYPE)0,         // Undefined                 = 14
+  (EFI_SMM_SAVE_STATE_IO_TYPE)0          // Undefined                 = 15
+};
+
+///
+/// The mode of the CPU at the time an SMI occurs
+///
+UINT8  mSmmSaveStateRegisterLma;
+
+/**
+  Read information from the CPU save state.
+
+  @param  Register  Specifies the CPU register to read form the save state.
+
+  @retval 0   Register is not valid
+  @retval >0  Index into mSmmCpuWidthOffset[] associated with Register
+
+**/
+UINTN
+GetRegisterIndex (
+  IN EFI_SMM_SAVE_STATE_REGISTER  Register
+  )
+{
+  UINTN  Index;
+  UINTN  Offset;
+
+  for (Index = 0, Offset = SMM_SAVE_STATE_REGISTER_MAX_INDEX; mSmmCpuRegisterRanges[Index].Length != 0; Index++) {
+    if ((Register >= mSmmCpuRegisterRanges[Index].Start) && (Register <= mSmmCpuRegisterRanges[Index].End)) {
+      return Register - mSmmCpuRegisterRanges[Index].Start + Offset;
+    }
+
+    Offset += mSmmCpuRegisterRanges[Index].Length;
+  }
+
+  return 0;
+}
+
+/**
+  Read a CPU Save State register on the target processor.
+
+  This function abstracts the differences that whether the CPU Save State register is in the
+  IA32 CPU Save State Map or X64 CPU Save State Map.
+
+  This function supports reading a CPU Save State register in SMBase relocation handler.
+
+  @param[in]  CpuIndex       Specifies the zero-based index of the CPU save state.
+  @param[in]  RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
+  @param[in]  Width          The number of bytes to read from the CPU save state.
+  @param[out] Buffer         Upon return, this holds the CPU register value read from the save state.
+
+  @retval EFI_SUCCESS           The register was read from Save State.
+  @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
+  @retval EFI_INVALID_PARAMETER  This or Buffer is NULL.
+
+**/
+EFI_STATUS
+ReadSaveStateRegisterByIndex (
+  IN UINTN  CpuIndex,
+  IN UINTN  RegisterIndex,
+  IN UINTN  Width,
+  OUT VOID  *Buffer
+  )
+{
+  SMRAM_SAVE_STATE_MAP  *CpuSaveState;
+
+  if (RegisterIndex == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  CpuSaveState = gSmst->CpuSaveState[CpuIndex];
+
+  if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
+    //
+    // If 32-bit mode width is zero, then the specified register can not be accessed
+    //
+    if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
+    //
+    if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Write return buffer
+    //
+    ASSERT (CpuSaveState != NULL);
+    CopyMem (Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Width);
+  } else {
+    //
+    // If 64-bit mode width is zero, then the specified register can not be accessed
+    //
+    if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
+    //
+    if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Write at most 4 of the lower bytes of the return buffer
+    //
+    CopyMem (Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, MIN (4, Width));
+    if (Width > 4) {
+      //
+      // Write at most 4 of the upper bytes of the return buffer
+      //
+      CopyMem ((UINT8 *)Buffer + 4, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, Width - 4);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Read a CPU Save State register on the target processor.
+
+  This function abstracts the differences that whether the CPU Save State register is in the
+  IA32 CPU Save State Map or X64 CPU Save State Map.
+
+  This function supports reading a CPU Save State register in SMBase relocation handler.
+
+  @param[in]  CpuIndex       Specifies the zero-based index of the CPU save state.
+  @param[in]  RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
+  @param[in]  Width          The number of bytes to read from the CPU save state.
+  @param[out] Buffer         Upon return, this holds the CPU register value read from the save state.
+
+  @retval EFI_SUCCESS           The register was read from Save State.
+  @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL, or Width does not meet requirement per Register type.
+
+**/
+EFI_STATUS
+EFIAPI
+ReadSaveStateRegister (
+  IN UINTN                        CpuIndex,
+  IN EFI_SMM_SAVE_STATE_REGISTER  Register,
+  IN UINTN                        Width,
+  OUT VOID                        *Buffer
+  )
+{
+  SMRAM_SAVE_STATE_MAP        *CpuSaveState;
+  EFI_SMM_SAVE_STATE_IO_INFO  *IoInfo;
+
+  CpuSaveState = gSmst->CpuSaveState[CpuIndex];
+  //
+  // Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA
+  //
+  if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
+    //
+    // Only byte access is supported for this register
+    //
+    if (Width != 1) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *(UINT8 *)Buffer = mSmmSaveStateRegisterLma;
+
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Check for special EFI_SMM_SAVE_STATE_REGISTER_IO
+  //
+  if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
+    //
+    // Check SMM IO Trap Offset valid bit
+    //
+    if (!(CpuSaveState->x64.SMM_IO_TRAP & 0x02)) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // Zero the IoInfo structure that will be returned in Buffer
+    //
+    IoInfo = (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer;
+    ZeroMem (IoInfo, sizeof (EFI_SMM_SAVE_STATE_IO_INFO));
+
+    //
+    // Use hard code to fill in all the fields of the IoInfo structure
+    //
+    IoInfo->IoPort  = (UINT16)(CpuSaveState->x64.SMM_IO_TRAP >> 16);
+    IoInfo->IoWidth = EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8;
+    IoInfo->IoType  = EFI_SMM_SAVE_STATE_IO_TYPE_INPUT;
+    IoInfo->IoData  = (UINT64)IoRead8 ((CpuSaveState->x64.SMM_IO_TRAP >> 16));
+
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Convert Register to a register lookup table index
+  //
+  return ReadSaveStateRegisterByIndex (CpuIndex, GetRegisterIndex (Register), Width, Buffer);
+}
+
+/**
+  Write value to a CPU Save State register on the target processor.
+
+  This function abstracts the differences that whether the CPU Save State register is in the
+  IA32 CPU Save State Map or X64 CPU Save State Map.
+
+  This function supports writing a CPU Save State register in SMBase relocation handler.
+
+  @param[in] CpuIndex       Specifies the zero-based index of the CPU save state.
+  @param[in] RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
+  @param[in] Width          The number of bytes to read from the CPU save state.
+  @param[in] Buffer         Upon entry, this holds the new CPU register value.
+
+  @retval EFI_SUCCESS           The register was written to Save State.
+  @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
+  @retval EFI_INVALID_PARAMETER  ProcessorIndex or Width is not correct.
+
+**/
+EFI_STATUS
+EFIAPI
+WriteSaveStateRegister (
+  IN UINTN                        CpuIndex,
+  IN EFI_SMM_SAVE_STATE_REGISTER  Register,
+  IN UINTN                        Width,
+  IN CONST VOID                   *Buffer
+  )
+{
+  UINTN                 RegisterIndex;
+  SMRAM_SAVE_STATE_MAP  *CpuSaveState;
+
+  //
+  // Writes to EFI_SMM_SAVE_STATE_REGISTER_LMA are ignored
+  //
+  if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Writes to EFI_SMM_SAVE_STATE_REGISTER_IO are not supported
+  //
+  if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Convert Register to a register lookup table index
+  //
+  RegisterIndex = GetRegisterIndex (Register);
+  if (RegisterIndex == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  CpuSaveState = gSmst->CpuSaveState[CpuIndex];
+
+  //
+  // Do not write non-writable SaveState, because it will cause exception.
+  //
+  if (!mSmmCpuWidthOffset[RegisterIndex].Writeable) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check CPU mode
+  //
+  if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
+    //
+    // If 32-bit mode width is zero, then the specified register can not be accessed
+    //
+    if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
+    //
+    if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Write SMM State register
+    //
+    ASSERT (CpuSaveState != NULL);
+    CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Buffer, Width);
+  } else {
+    //
+    // If 64-bit mode width is zero, then the specified register can not be accessed
+    //
+    if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
+    //
+    if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Write at most 4 of the lower bytes of SMM State register
+    //
+    CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, Buffer, MIN (4, Width));
+    if (Width > 4) {
+      //
+      // Write at most 4 of the upper bytes of SMM State register
+      //
+      CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer + 4, Width - 4);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Hook the code executed immediately after an RSM instruction on the currently
+  executing CPU.  The mode of code executed immediately after RSM must be
+  detected, and the appropriate hook must be selected.  Always clear the auto
+  HALT restart flag if it is set.
+
+  @param[in] CpuIndex                 The processor index for the currently
+                                      executing CPU.
+  @param[in] CpuState                 Pointer to SMRAM Save State Map for the
+                                      currently executing CPU.
+  @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
+                                      32-bit mode from 64-bit SMM.
+  @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
+                                      same mode as SMM.
+
+  @retval The value of the original instruction pointer before it was hooked.
+
+**/
+UINT64
+EFIAPI
+HookReturnFromSmm (
+  IN UINTN              CpuIndex,
+  SMRAM_SAVE_STATE_MAP  *CpuState,
+  UINT64                NewInstructionPointer32,
+  UINT64                NewInstructionPointer
+  )
+{
+  UINT64  OriginalInstructionPointer;
+
+  OriginalInstructionPointer = SmmCpuFeaturesHookReturnFromSmm (
+                                 CpuIndex,
+                                 CpuState,
+                                 NewInstructionPointer32,
+                                 NewInstructionPointer
+                                 );
+  if (OriginalInstructionPointer != 0) {
+    return OriginalInstructionPointer;
+  }
+
+  if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
+    OriginalInstructionPointer = (UINT64)CpuState->x86._EIP;
+    CpuState->x86._EIP         = (UINT32)NewInstructionPointer;
+    //
+    // Clear the auto HALT restart flag so the RSM instruction returns
+    // program control to the instruction following the HLT instruction.
+    //
+    if ((CpuState->x86.AutoHALTRestart & BIT0) != 0) {
+      CpuState->x86.AutoHALTRestart &= ~BIT0;
+    }
+  } else {
+    OriginalInstructionPointer = CpuState->x64._RIP;
+    if ((CpuState->x64.EFER & LMA) == 0) {
+      CpuState->x64._RIP = (UINT32)NewInstructionPointer32;
+    } else {
+      CpuState->x64._RIP = (UINT32)NewInstructionPointer;
+    }
+
+    //
+    // Clear the auto HALT restart flag so the RSM instruction returns
+    // program control to the instruction following the HLT instruction.
+    //
+    if ((CpuState->x64.AutoHALTRestart & BIT0) != 0) {
+      CpuState->x64.AutoHALTRestart &= ~BIT0;
+    }
+  }
+
+  return OriginalInstructionPointer;
+}
+
+/**
+  Get the size of the SMI Handler in bytes.
+
+  @retval The size, in bytes, of the SMI Handler.
+
+**/
+UINTN
+EFIAPI
+GetSmiHandlerSize (
+  VOID
+  )
+{
+  UINTN  Size;
+
+  Size = SmmCpuFeaturesGetSmiHandlerSize ();
+  if (Size != 0) {
+    return Size;
+  }
+
+  return gcSmiHandlerSize;
+}
+
+/**
+  Install the SMI handler for the CPU specified by CpuIndex.  This function
+  is called by the CPU that was elected as monarch during System Management
+  Mode initialization.
+
+  @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.
+                        The value must be between 0 and the NumberOfCpus field
+                        in the System Management System Table (SMST).
+  @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.
+  @param[in] SmiStack   The stack to use when an SMI is processed by the
+                        the CPU specified by CpuIndex.
+  @param[in] StackSize  The size, in bytes, if the stack used when an SMI is
+                        processed by the CPU specified by CpuIndex.
+  @param[in] GdtBase    The base address of the GDT to use when an SMI is
+                        processed by the CPU specified by CpuIndex.
+  @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is
+                        processed by the CPU specified by CpuIndex.
+  @param[in] IdtBase    The base address of the IDT to use when an SMI is
+                        processed by the CPU specified by CpuIndex.
+  @param[in] IdtSize    The size, in bytes, of the IDT used when an SMI is
+                        processed by the CPU specified by CpuIndex.
+  @param[in] Cr3        The base address of the page tables to use when an SMI
+                        is processed by the CPU specified by CpuIndex.
+**/
+VOID
+EFIAPI
+InstallSmiHandler (
+  IN UINTN   CpuIndex,
+  IN UINT32  SmBase,
+  IN VOID    *SmiStack,
+  IN UINTN   StackSize,
+  IN UINTN   GdtBase,
+  IN UINTN   GdtSize,
+  IN UINTN   IdtBase,
+  IN UINTN   IdtSize,
+  IN UINT32  Cr3
+  )
+{
+  PROCESSOR_SMM_DESCRIPTOR  *Psd;
+  UINT32                    CpuSmiStack;
+
+  //
+  // Initialize PROCESSOR_SMM_DESCRIPTOR
+  //
+  Psd = (PROCESSOR_SMM_DESCRIPTOR *)(VOID *)((UINTN)SmBase + SMM_PSD_OFFSET);
+  CopyMem (Psd, &gcPsd, sizeof (gcPsd));
+  Psd->SmmGdtPtr  = (UINT64)GdtBase;
+  Psd->SmmGdtSize = (UINT32)GdtSize;
+
+  if (SmmCpuFeaturesGetSmiHandlerSize () != 0) {
+    //
+    // Install SMI handler provided by library
+    //
+    SmmCpuFeaturesInstallSmiHandler (
+      CpuIndex,
+      SmBase,
+      SmiStack,
+      StackSize,
+      GdtBase,
+      GdtSize,
+      IdtBase,
+      IdtSize,
+      Cr3
+      );
+    return;
+  }
+
+  InitShadowStack (CpuIndex, (VOID *)((UINTN)SmiStack + StackSize));
+
+  //
+  // Initialize values in template before copy
+  //
+  CpuSmiStack = (UINT32)((UINTN)SmiStack + StackSize - sizeof (UINTN));
+  PatchInstructionX86 (gPatchSmiStack, CpuSmiStack, 4);
+  PatchInstructionX86 (gPatchSmiCr3, Cr3, 4);
+  PatchInstructionX86 (gPatchSmbase, SmBase, 4);
+  gSmiHandlerIdtr.Base  = IdtBase;
+  gSmiHandlerIdtr.Limit = (UINT16)(IdtSize - 1);
+
+  //
+  // Set the value at the top of the CPU stack to the CPU Index
+  //
+  *(UINTN *)(UINTN)CpuSmiStack = CpuIndex;
+
+  //
+  // Copy template to CPU specific SMI handler location
+  //
+  CopyMem (
+    (VOID *)((UINTN)SmBase + SMM_HANDLER_OFFSET),
+    (VOID *)gcSmiHandlerTemplate,
+    gcSmiHandlerSize
+    );
+}
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114604): https://edk2.groups.io/g/devel/message/114604
Mute This Topic: https://groups.io/mt/103975487/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 30/32] AMD/VanGoghBoard: Check in EDK2 override files
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (28 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 29/32] AMD/VanGoghBoard: Check in SmramSaveState module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module Zhai, MingXin (Duke) via groups.io
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Duke Zhai, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V3: Improve coding style follow edk2 C coding standard.
  1.Remove macro definition extra underscores.
  2.Putting some AMD copyright in the right place.

In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  ChachaniBoard Use FSP for open source. FSP is needed to provide some
  AGESA related pcds as the interface for Platform BIOS.
  Override those EDK2 files to support reading AGESA-related PCDs from FSP.

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>
---
 .../edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c | 1520 +++++++++++++
 .../MdeModulePkg/Universal/PCD/Dxe/Pcd.inf    |  359 ++++
 .../edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c | 1876 +++++++++++++++++
 .../MdeModulePkg/Universal/PCD/Pei/Pcd.inf    |  361 ++++
 .../Register/Intel/SmramSaveStateMap.h        |  324 +++
 5 files changed, 4440 insertions(+)
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Intel/SmramSaveStateMap.h

diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c
new file mode 100644
index 0000000000..5533786b2c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.c
@@ -0,0 +1,1520 @@
+/** @file
+  PCD DXE driver manage all PCD entry initialized in PEI phase and DXE phase, and
+  produce the implementation of native PCD protocol and EFI_PCD_PROTOCOL defined in
+  PI 1.4a Vol3.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Service.h"
+
+extern EFI_GUID  gEfiAmdAgesaModulePkgTokenSpaceGuid;
+extern EFI_GUID  gEfiAmdAgesaPkgTokenSpaceGuid;
+extern EFI_GUID  gFspEfiGetPcdInfoProtocolGuid;
+extern EFI_GUID  gFspEfiPcdProtocolGuid;
+
+// Cache the FSP PiPcd Protocols.
+STATIC EFI_PCD_PROTOCOL           *CachedFspPiPcdProtocol;
+STATIC EFI_GET_PCD_INFO_PROTOCOL  *CachedFspPiGetPcdInfoProtocol;
+
+STATIC
+BOOLEAN
+CheckPcdInFsp (
+  IN CONST EFI_GUID  *InputGuid
+  )
+{
+  if (  (FixedPcdGet8 (PcdFspModeSelection) == 0)                        // Dispatch mode
+     && (  CompareGuid (InputGuid, &gEfiAmdAgesaModulePkgTokenSpaceGuid) // AgesaModulePkg
+        || CompareGuid (InputGuid, &gEfiAmdAgesaPkgTokenSpaceGuid)       // AgesaPkg
+        || CompareGuid (InputGuid, &gAmdFspPkgGuid)                      // FspPkg
+        || CompareGuid (InputGuid, &gAmdCpmPkgTokenSpaceGuid)))          // AmdCpmPkg
+  {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+VOID
+EFIAPI
+FspPiPcdProtocolInstalled (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  gBS->LocateProtocol (&gFspEfiPcdProtocolGuid, NULL, (VOID **)&CachedFspPiPcdProtocol);
+  gBS->CloseEvent (Event);
+  return;
+}
+
+VOID
+EFIAPI
+FspPiGetPcdInfoProtocolInstalled (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  gBS->LocateProtocol (&gFspEfiGetPcdInfoProtocolGuid, NULL, (VOID **)&CachedFspPiGetPcdInfoProtocol);
+  gBS->CloseEvent (Event);
+  return;
+}
+
+STATIC EFI_EVENT  mFspPiPcdProtocolInstalledEvent;
+STATIC EFI_EVENT  mFspPiGetPcdInfoProtocolInstalledEvent;
+
+///
+/// PCD database lock.
+///
+EFI_LOCK  mPcdDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
+
+///
+/// PCD_PROTOCOL the EDKII native implementation which support dynamic
+/// type and dynamicEx type PCDs.
+///
+PCD_PROTOCOL  mPcdInstance = {
+  DxePcdSetSku,
+
+  DxePcdGet8,
+  DxePcdGet16,
+  DxePcdGet32,
+  DxePcdGet64,
+  DxePcdGetPtr,
+  DxePcdGetBool,
+  DxePcdGetSize,
+
+  DxePcdGet8Ex,
+  DxePcdGet16Ex,
+  DxePcdGet32Ex,
+  DxePcdGet64Ex,
+  DxePcdGetPtrEx,
+  DxePcdGetBoolEx,
+  DxePcdGetSizeEx,
+
+  DxePcdSet8,
+  DxePcdSet16,
+  DxePcdSet32,
+  DxePcdSet64,
+  DxePcdSetPtr,
+  DxePcdSetBool,
+
+  DxePcdSet8Ex,
+  DxePcdSet16Ex,
+  DxePcdSet32Ex,
+  DxePcdSet64Ex,
+  DxePcdSetPtrEx,
+  DxePcdSetBoolEx,
+
+  DxeRegisterCallBackOnSet,
+  DxeUnRegisterCallBackOnSet,
+  DxePcdGetNextToken,
+  DxePcdGetNextTokenSpace
+};
+
+///
+/// EFI_PCD_PROTOCOL is defined in PI 1.2 Vol 3 which only support dynamicEx type
+/// PCD.
+///
+EFI_PCD_PROTOCOL  mEfiPcdInstance = {
+  DxePcdSetSku,
+  DxePcdGet8Ex,
+  DxePcdGet16Ex,
+  DxePcdGet32Ex,
+  DxePcdGet64Ex,
+  DxePcdGetPtrEx,
+  DxePcdGetBoolEx,
+  DxePcdGetSizeEx,
+  DxePcdSet8Ex,
+  DxePcdSet16Ex,
+  DxePcdSet32Ex,
+  DxePcdSet64Ex,
+  DxePcdSetPtrEx,
+  DxePcdSetBoolEx,
+  (EFI_PCD_PROTOCOL_CALLBACK_ON_SET)DxeRegisterCallBackOnSet,
+  (EFI_PCD_PROTOCOL_CANCEL_CALLBACK)DxeUnRegisterCallBackOnSet,
+  DxePcdGetNextToken,
+  DxePcdGetNextTokenSpace
+};
+
+///
+/// Instance of GET_PCD_INFO_PROTOCOL protocol is EDKII native implementation.
+/// This protocol instance support dynamic and dynamicEx type PCDs.
+///
+GET_PCD_INFO_PROTOCOL  mGetPcdInfoInstance = {
+  DxeGetPcdInfoGetInfo,
+  DxeGetPcdInfoGetInfoEx,
+  DxeGetPcdInfoGetSku
+};
+
+///
+/// Instance of EFI_GET_PCD_INFO_PROTOCOL which is defined in PI 1.2.1 Vol 3.
+/// This PPI instance only support dyanmicEx type PCD.
+///
+EFI_GET_PCD_INFO_PROTOCOL  mEfiGetPcdInfoInstance = {
+  DxeGetPcdInfoGetInfoEx,
+  DxeGetPcdInfoGetSku
+};
+
+EFI_HANDLE  mPcdHandle      = NULL;
+UINTN       mVpdBaseAddress = 0;
+
+/**
+  Main entry for PCD DXE driver.
+
+  This routine initialize the PCD database and install PCD_PROTOCOL.
+
+  @param ImageHandle     Image handle for PCD DXE driver.
+  @param SystemTable     Pointer to SystemTable.
+
+  @return Status of gBS->InstallProtocolInterface()
+
+**/
+EFI_STATUS
+EFIAPI
+PcdDxeInit (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  VOID        *Registration;
+
+  //
+  // Make sure the Pcd Protocol is not already installed in the system
+  //
+
+  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gPcdProtocolGuid);
+
+  BuildPcdDxeDataBase ();
+
+  //
+  // Install PCD_PROTOCOL to handle dynamic type PCD
+  // Install EFI_PCD_PROTOCOL to handle dynamicEx type PCD
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mPcdHandle,
+                  &gPcdProtocolGuid,
+                  &mPcdInstance,
+                  &gEfiPcdProtocolGuid,
+                  &mEfiPcdInstance,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Install GET_PCD_INFO_PROTOCOL to handle dynamic type PCD
+  // Install EFI_GET_PCD_INFO_PROTOCOL to handle dynamicEx type PCD
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mPcdHandle,
+                  &gGetPcdInfoProtocolGuid,
+                  &mGetPcdInfoInstance,
+                  &gEfiGetPcdInfoProtocolGuid,
+                  &mEfiGetPcdInfoInstance,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  // Wait FSP Pcd Protocol.
+  gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, FspPiPcdProtocolInstalled, NULL, &mFspPiPcdProtocolInstalledEvent);
+  gBS->RegisterProtocolNotify (&gFspEfiPcdProtocolGuid, mFspPiPcdProtocolInstalledEvent, &Registration);
+  gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, FspPiGetPcdInfoProtocolInstalled, NULL, &mFspPiGetPcdInfoProtocolInstalledEvent);
+  gBS->RegisterProtocolNotify (&gFspEfiGetPcdInfoProtocolGuid, mFspPiGetPcdInfoProtocolInstalledEvent, &Registration);
+
+  //
+  // Register callback function upon VariableLockProtocol
+  // to lock the variables referenced by DynamicHii PCDs with RO property set in *.dsc.
+  //
+  EfiCreateProtocolNotifyEvent (
+    &gEdkiiVariableLockProtocolGuid,
+    TPL_CALLBACK,
+    VariableLockCallBack,
+    NULL,
+    &Registration
+    );
+
+  //
+  // Cache VpdBaseAddress in entry point for the following usage.
+  //
+
+  //
+  // PcdVpdBaseAddress64 is DynamicEx PCD only. So, DxePcdGet64Ex() is used to get its value.
+  //
+  mVpdBaseAddress = (UINTN)DxePcdGet64Ex (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdVpdBaseAddress64));
+  if (mVpdBaseAddress == 0) {
+    //
+    // PcdVpdBaseAddress64 is not set, get value from PcdVpdBaseAddress.
+    //
+    mVpdBaseAddress = (UINTN)PcdGet32 (PcdVpdBaseAddress);
+  }
+
+  return Status;
+}
+
+/**
+  Retrieve additional information associated with a PCD token in the default token space.
+
+  This includes information such as the type of value the TokenNumber is associated with as well as possible
+  human readable name that is associated with the token.
+
+  @param[in]    TokenNumber The PCD token number.
+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.
+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+  @retval  EFI_SUCCESS      The PCD information was returned successfully.
+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+DxeGetPcdInfoGetInfo (
+  IN        UINTN         TokenNumber,
+  OUT       EFI_PCD_INFO  *PcdInfo
+  )
+{
+  return DxeGetPcdInfo (NULL, TokenNumber, PcdInfo);
+}
+
+/**
+  Retrieve additional information associated with a PCD token.
+
+  This includes information such as the type of value the TokenNumber is associated with as well as possible
+  human readable name that is associated with the token.
+
+  @param[in]    Guid        The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]    TokenNumber The PCD token number.
+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.
+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+  @retval  EFI_SUCCESS      The PCD information was returned successfully.
+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+DxeGetPcdInfoGetInfoEx (
+  IN CONST  EFI_GUID      *Guid,
+  IN        UINTN         TokenNumber,
+  OUT       EFI_PCD_INFO  *PcdInfo
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiGetPcdInfoProtocol != NULL);
+    return CachedFspPiGetPcdInfoProtocol->GetInfo (Guid, TokenNumber, PcdInfo);
+  }
+
+  return DxeGetPcdInfo (Guid, TokenNumber, PcdInfo);
+}
+
+/**
+  Retrieve the currently set SKU Id.
+
+  @return   The currently set SKU Id. If the platform has not set at a SKU Id, then the
+            default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU
+            Id is returned.
+**/
+UINTN
+EFIAPI
+DxeGetPcdInfoGetSku (
+  VOID
+  )
+{
+  return (UINTN)mPcdDatabase.DxeDb->SystemSkuId;
+}
+
+/**
+  Sets the SKU value for subsequent calls to set or get PCD token values.
+
+  SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.
+  SetSku() is normally called only once by the system.
+
+  For each item (token), the database can hold a single value that applies to all SKUs,
+  or multiple values, where each value is associated with a specific SKU Id. Items with multiple,
+  SKU-specific values are called SKU enabled.
+
+  The SKU Id of zero is reserved as a default.
+  For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the
+  single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the
+  last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,
+  the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been
+  set for that Id, the results are unpredictable.
+
+  @param[in]  SkuId The SKU value that will be used when the PCD service will retrieve and
+              set values associated with a PCD token.
+
+**/
+VOID
+EFIAPI
+DxePcdSetSku (
+  IN  UINTN  SkuId
+  )
+{
+  SKU_ID      *SkuIdTable;
+  UINTN       Index;
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "PcdDxe - SkuId 0x%lx is to be set.\n", (SKU_ID)SkuId));
+
+  if (SkuId == mPcdDatabase.DxeDb->SystemSkuId) {
+    //
+    // The input SKU Id is equal to current SKU Id, return directly.
+    //
+    DEBUG ((DEBUG_INFO, "PcdDxe - SkuId is same to current system Sku.\n"));
+    return;
+  }
+
+  if (mPcdDatabase.DxeDb->SystemSkuId != (SKU_ID)0) {
+    DEBUG ((DEBUG_ERROR, "PcdDxe - The SKU Id could be changed only once."));
+    DEBUG ((
+      DEBUG_ERROR,
+      "PcdDxe - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",
+      mPcdDatabase.DxeDb->SystemSkuId,
+      (SKU_ID)SkuId
+      ));
+    ASSERT (FALSE);
+    return;
+  }
+
+  SkuIdTable = (SKU_ID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->SkuIdTableOffset);
+  for (Index = 0; Index < SkuIdTable[0]; Index++) {
+    if (SkuId == SkuIdTable[Index + 1]) {
+      DEBUG ((DEBUG_INFO, "PcdDxe - SkuId is found in SkuId table.\n"));
+      Status = UpdatePcdDatabase (SkuId, TRUE);
+      if (!EFI_ERROR (Status)) {
+        mPcdDatabase.DxeDb->SystemSkuId = (SKU_ID)SkuId;
+        DEBUG ((DEBUG_INFO, "PcdDxe - Set current SKU Id to 0x%lx.\n", (SKU_ID)SkuId));
+        return;
+      }
+    }
+  }
+
+  //
+  // Invalid input SkuId, the default SKU Id will be still used for the system.
+  //
+  DEBUG ((DEBUG_ERROR, "PcdDxe - Invalid input SkuId, the default SKU Id will be still used.\n"));
+  return;
+}
+
+/**
+  Retrieves an 8-bit value for a given PCD token.
+
+  Retrieves the current byte-sized value for a PCD token number.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The UINT8 value.
+
+**/
+UINT8
+EFIAPI
+DxePcdGet8 (
+  IN UINTN  TokenNumber
+  )
+{
+  return *((UINT8 *)GetWorker (TokenNumber, sizeof (UINT8)));
+}
+
+/**
+  Retrieves an 16-bit value for a given PCD token.
+
+  Retrieves the current 16-bits value for a PCD token number.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The UINT16 value.
+
+**/
+UINT16
+EFIAPI
+DxePcdGet16 (
+  IN UINTN  TokenNumber
+  )
+{
+  return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
+}
+
+/**
+  Retrieves an 32-bit value for a given PCD token.
+
+  Retrieves the current 32-bits value for a PCD token number.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The UINT32 value.
+
+**/
+UINT32
+EFIAPI
+DxePcdGet32 (
+  IN UINTN  TokenNumber
+  )
+{
+  return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
+}
+
+/**
+  Retrieves an 64-bit value for a given PCD token.
+
+  Retrieves the current 64-bits value for a PCD token number.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The UINT64 value.
+
+**/
+UINT64
+EFIAPI
+DxePcdGet64 (
+  IN UINTN  TokenNumber
+  )
+{
+  return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));
+}
+
+/**
+  Retrieves a pointer to a value for a given PCD token.
+
+  Retrieves the current pointer to the buffer for a PCD token number.
+  Do not make any assumptions about the alignment of the pointer that
+  is returned by this function call.  If the TokenNumber is invalid,
+  the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The pointer to the buffer to be retrived.
+
+**/
+VOID *
+EFIAPI
+DxePcdGetPtr (
+  IN UINTN  TokenNumber
+  )
+{
+  return GetWorker (TokenNumber, 0);
+}
+
+/**
+  Retrieves a Boolean value for a given PCD token.
+
+  Retrieves the current boolean value for a PCD token number.
+  Do not make any assumptions about the alignment of the pointer that
+  is returned by this function call.  If the TokenNumber is invalid,
+  the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The Boolean value.
+
+**/
+BOOLEAN
+EFIAPI
+DxePcdGetBool (
+  IN UINTN  TokenNumber
+  )
+{
+  return *((BOOLEAN *)GetWorker (TokenNumber, sizeof (BOOLEAN)));
+}
+
+/**
+  Retrieves the size of the value for a given PCD token.
+
+  Retrieves the current size of a particular PCD token.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+DxePcdGetSize (
+  IN UINTN  TokenNumber
+  )
+{
+  UINTN    Size;
+  UINT32   *LocalTokenNumberTable;
+  BOOLEAN  IsPeiDb;
+  UINTN    MaxSize;
+  UINTN    TmpTokenNumber;
+
+  //
+  // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+  // We have to decrement TokenNumber by 1 to make it usable
+  // as the array index.
+  //
+  TokenNumber--;
+
+  //
+  // Backup the TokenNumber passed in as GetPtrTypeSize need the original TokenNumber
+  //
+  TmpTokenNumber = TokenNumber;
+
+  // EBC compiler is very choosy. It may report warning about comparison
+  // between UINTN and 0 . So we add 1 in each size of the
+  // comparison.
+  ASSERT (TokenNumber + 1 < mPcdTotalTokenCount + 1);
+
+  // EBC compiler is very choosy. It may report warning about comparison
+  // between UINTN and 0 . So we add 1 in each size of the
+  // comparison.
+  IsPeiDb = (BOOLEAN)(TokenNumber + 1 < mPeiLocalTokenCount + 1);
+
+  TokenNumber = IsPeiDb ? TokenNumber :
+                (TokenNumber - mPeiLocalTokenCount);
+
+  LocalTokenNumberTable = IsPeiDb ? (UINT32 *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->LocalTokenNumberTableOffset)
+                                  : (UINT32 *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->LocalTokenNumberTableOffset);
+
+  Size = (LocalTokenNumberTable[TokenNumber] & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
+
+  if (Size == 0) {
+    //
+    // For pointer type, we need to scan the SIZE_TABLE to get the current size.
+    //
+    return GetPtrTypeSize (TmpTokenNumber, &MaxSize);
+  } else {
+    return Size;
+  }
+}
+
+/**
+  Retrieves an 8-bit value for a given PCD token.
+
+  Retrieves the 8-bit value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid          The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size 8-bit value for the PCD token.
+
+**/
+UINT8
+EFIAPI
+DxePcdGet8Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->Get8 (Guid, ExTokenNumber);
+  }
+
+  return *((UINT8 *)ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));
+}
+
+/**
+  Retrieves an 16-bit value for a given PCD token.
+
+  Retrieves the 16-bit value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size 16-bit value for the PCD token.
+
+**/
+UINT16
+EFIAPI
+DxePcdGet16Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->Get16 (Guid, ExTokenNumber);
+  }
+
+  return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));
+}
+
+/**
+  Retrieves an 32-bit value for a given PCD token.
+
+  Retrieves the 32-bit value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size 32-bit value for the PCD token.
+
+**/
+UINT32
+EFIAPI
+DxePcdGet32Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->Get32 (Guid, ExTokenNumber);
+  }
+
+  return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));
+}
+
+/**
+  Retrieves an 64-bit value for a given PCD token.
+
+  Retrieves the 64-bit value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size 64-bit value for the PCD token.
+
+**/
+UINT64
+EFIAPI
+DxePcdGet64Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->Get64 (Guid, ExTokenNumber);
+  }
+
+  return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));
+}
+
+/**
+  Retrieves a pointer to a value for a given PCD token.
+
+  Retrieves the current pointer to the buffer for a PCD token number.
+  Do not make any assumptions about the alignment of the pointer that
+  is returned by this function call.  If the TokenNumber is invalid,
+  the results are unpredictable.
+
+  @param[in]  Guid The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The pointer to the buffer to be retrived.
+
+**/
+VOID *
+EFIAPI
+DxePcdGetPtrEx (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->GetPtr (Guid, ExTokenNumber);
+  }
+
+  return ExGetWorker (Guid, ExTokenNumber, 0);
+}
+
+/**
+  Retrieves an Boolean value for a given PCD token.
+
+  Retrieves the Boolean value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size Boolean value for the PCD token.
+
+**/
+BOOLEAN
+EFIAPI
+DxePcdGetBoolEx (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->GetBool (Guid, ExTokenNumber);
+  }
+
+  return *((BOOLEAN *)ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));
+}
+
+/**
+  Retrieves the size of the value for a given PCD token.
+
+  Retrieves the current size of a particular PCD token.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  Guid The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+DxePcdGetSizeEx (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->GetSize (Guid, ExTokenNumber);
+  }
+
+  return DxePcdGetSize (GetExPcdTokenNumber (Guid, (UINT32)ExTokenNumber));
+}
+
+/**
+  Sets an 8-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet8 (
+  IN UINTN  TokenNumber,
+  IN UINT8  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 16-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet16 (
+  IN UINTN   TokenNumber,
+  IN UINT16  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 32-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet32 (
+  IN UINTN   TokenNumber,
+  IN UINT32  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 64-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet64 (
+  IN UINTN   TokenNumber,
+  IN UINT64  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets a value of a specified size for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+                              On input, if the SizeOfValue is greater than the maximum size supported
+                              for this TokenNumber then the output value of SizeOfValue will reflect
+                              the maximum size supported for this TokenNumber.
+  @param[in]  Buffer The buffer to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetPtr (
+  IN          UINTN  TokenNumber,
+  IN OUT      UINTN  *SizeOfBuffer,
+  IN          VOID   *Buffer
+  )
+{
+  return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
+}
+
+/**
+  Sets an Boolean value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetBool (
+  IN UINTN    TokenNumber,
+  IN BOOLEAN  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 8-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet8Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN UINT8           Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->Set8 (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 16-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet16Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN UINT16          Value
+  )
+{
+  //
+  // PcdSetNvStoreDefaultId should be set in PEI phase to take effect.
+  //
+  ASSERT (
+    !(CompareGuid (Guid, &gEfiMdeModulePkgTokenSpaceGuid) &&
+      (ExTokenNumber == PcdToken (PcdSetNvStoreDefaultId)))
+    );
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->Set16 (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 32-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet32Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN UINT32          Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->Set32 (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 64-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSet64Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN UINT64          Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->Set64 (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Sets a value of a specified size for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+                              On input, if the SizeOfValue is greater than the maximum size supported
+                              for this TokenNumber then the output value of SizeOfValue will reflect
+                              the maximum size supported for this TokenNumber.
+  @param[in]  Buffer The buffer to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetPtrEx (
+  IN            CONST EFI_GUID  *Guid,
+  IN            UINTN           ExTokenNumber,
+  IN OUT        UINTN           *SizeOfBuffer,
+  IN            VOID            *Buffer
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->SetPtr (Guid, ExTokenNumber, SizeOfBuffer, Buffer);
+  }
+
+  return ExSetWorker (ExTokenNumber, Guid, Buffer, SizeOfBuffer, TRUE);
+}
+
+/**
+  Sets an Boolean value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdSetBoolEx (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN BOOLEAN         Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    ASSERT (CachedFspPiPcdProtocol != NULL);
+    return CachedFspPiPcdProtocol->SetBool (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Specifies a function to be called anytime the value of a designated token is changed.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+  @retval EFI_SUCCESS  The PCD service has successfully established a call event
+                        for the CallBackToken requested.
+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeRegisterCallBackOnSet (
+  IN  CONST EFI_GUID         *Guid  OPTIONAL,
+  IN  UINTN                  TokenNumber,
+  IN  PCD_PROTOCOL_CALLBACK  CallBackFunction
+  )
+{
+  EFI_STATUS  Status;
+
+  if (CallBackFunction == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Aquire lock to prevent reentrance from TPL_CALLBACK level
+  //
+  EfiAcquireLock (&mPcdDatabaseLock);
+
+  Status = DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
+
+  EfiReleaseLock (&mPcdDatabaseLock);
+
+  return Status;
+}
+
+/**
+  Cancels a previously set callback function for a particular PCD token number.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+  @retval EFI_SUCCESS  The PCD service has successfully established a call event
+                        for the CallBackToken requested.
+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxeUnRegisterCallBackOnSet (
+  IN  CONST EFI_GUID         *Guid  OPTIONAL,
+  IN  UINTN                  TokenNumber,
+  IN  PCD_PROTOCOL_CALLBACK  CallBackFunction
+  )
+{
+  EFI_STATUS  Status;
+
+  if (CallBackFunction == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Aquire lock to prevent reentrance from TPL_CALLBACK level
+  //
+  EfiAcquireLock (&mPcdDatabaseLock);
+
+  Status = DxeUnRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction);
+
+  EfiReleaseLock (&mPcdDatabaseLock);
+
+  return Status;
+}
+
+/**
+  Retrieves the next valid token number in a given namespace.
+
+  This is useful since the PCD infrastructure contains a sparse list of token numbers,
+  and one cannot a priori know what token numbers are valid in the database.
+
+  If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.
+  If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.
+  If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.
+  If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.
+  The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.
+  If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.
+  If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+  If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+
+
+  @param[in]      Guid    The 128-bit unique value that designates the namespace from which to retrieve the next token.
+                          This is an optional parameter that may be NULL.  If this parameter is NULL, then a request is
+                          being made to retrieve tokens from the default token space.
+  @param[in, out] TokenNumber
+                          A pointer to the PCD token number to use to find the subsequent token number.
+
+  @retval EFI_SUCCESS   The PCD service has retrieved the next valid token number.
+  @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdGetNextToken (
+  IN CONST EFI_GUID  *Guid  OPTIONAL,
+  IN OUT   UINTN     *TokenNumber
+  )
+{
+  EFI_STATUS  Status;
+  BOOLEAN     PeiExMapTableEmpty;
+  BOOLEAN     DxeExMapTableEmpty;
+
+  Status             = EFI_NOT_FOUND;
+  PeiExMapTableEmpty = mPeiExMapTableEmpty;
+  DxeExMapTableEmpty = mDxeExMapTableEmpty;
+
+  //
+  // Scan the local token space
+  //
+  if (Guid == NULL) {
+    // EBC compiler is very choosy. It may report warning about comparison
+    // between UINTN and 0 . So we add 1 in each size of the
+    // comparison.
+    if (((*TokenNumber + 1 > mPeiNexTokenCount + 1) && (*TokenNumber + 1 <= mPeiLocalTokenCount + 1)) ||
+        ((*TokenNumber + 1 > (mPeiLocalTokenCount + mDxeNexTokenCount + 1))))
+    {
+      return EFI_NOT_FOUND;
+    }
+
+    (*TokenNumber)++;
+    if ((*TokenNumber + 1 > mPeiNexTokenCount + 1) &&
+        (*TokenNumber + 1 <= mPeiLocalTokenCount + 1))
+    {
+      //
+      // The first Non-Ex type Token Number for DXE PCD
+      // database is mPeiLocalTokenCount + 1
+      //
+      if (mDxeNexTokenCount > 0) {
+        *TokenNumber = mPeiLocalTokenCount + 1;
+      } else {
+        *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+        return EFI_NOT_FOUND;
+      }
+    } else if (*TokenNumber + 1 > mDxeNexTokenCount + mPeiLocalTokenCount + 1) {
+      *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+      return EFI_NOT_FOUND;
+    }
+
+    return EFI_SUCCESS;
+  }
+
+  if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (!PeiExMapTableEmpty) {
+    Status = ExGetNextTokeNumber (
+               Guid,
+               TokenNumber,
+               (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset),
+               mPeiGuidTableSize,
+               (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),
+               mPeiExMapppingTableSize
+               );
+  }
+
+  if (Status == EFI_SUCCESS) {
+    return Status;
+  }
+
+  if (!DxeExMapTableEmpty) {
+    Status = ExGetNextTokeNumber (
+               Guid,
+               TokenNumber,
+               (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset),
+               mDxeGuidTableSize,
+               (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),
+               mDxeExMapppingTableSize
+               );
+  }
+
+  return Status;
+}
+
+/**
+  Get all token space guid table which is different with given token space guid.
+
+  @param ExMapTableSize  The size of ExMapTable in item
+  @param ExMapTable      Token space guid table that want to be scaned.
+  @param GuidTable       Guid table
+
+  @return all token space guid table which is different with given token space guid.
+
+**/
+EFI_GUID **
+GetDistinctTokenSpace (
+  IN OUT    UINTN              *ExMapTableSize,
+  IN        DYNAMICEX_MAPPING  *ExMapTable,
+  IN        EFI_GUID           *GuidTable
+  )
+{
+  EFI_GUID  **DistinctTokenSpace;
+  UINTN     OldGuidIndex;
+  UINTN     TsIdx;
+  UINTN     TempTsIdx;
+  UINTN     Idx;
+  BOOLEAN   Match;
+
+  DistinctTokenSpace = AllocateZeroPool (*ExMapTableSize * sizeof (EFI_GUID *));
+  ASSERT (DistinctTokenSpace != NULL);
+
+  TsIdx                     = 0;
+  OldGuidIndex              = ExMapTable[0].ExGuidIndex;
+  DistinctTokenSpace[TsIdx] = &GuidTable[OldGuidIndex];
+  for (Idx = 1; Idx < *ExMapTableSize; Idx++) {
+    Match        = FALSE;
+    OldGuidIndex = ExMapTable[Idx].ExGuidIndex;
+    for (TempTsIdx = 0; TempTsIdx <= TsIdx; TempTsIdx++) {
+      if (&GuidTable[OldGuidIndex] == DistinctTokenSpace[TempTsIdx]) {
+        //
+        // Have recorded this GUID.
+        //
+        Match = TRUE;
+        break;
+      }
+    }
+
+    if (!Match) {
+      DistinctTokenSpace[++TsIdx] = &GuidTable[OldGuidIndex];
+    }
+  }
+
+  //
+  // The total number of Distinct Token Space
+  // is TsIdx + 1 because we use TsIdx as a index
+  // to the DistinctTokenSpace[]
+  //
+  *ExMapTableSize = TsIdx + 1;
+  return DistinctTokenSpace;
+}
+
+/**
+  Retrieves the next valid PCD token namespace for a given namespace.
+
+  Gets the next valid token namespace for a given namespace. This is useful to traverse the valid
+  token namespaces on a platform.
+
+  @param[in, out]   Guid    An indirect pointer to EFI_GUID. On input it designates a known token
+                            namespace from which the search will start. On output, it designates the next valid
+                            token namespace on the platform. If *Guid is NULL, then the GUID of the first token
+                            space of the current platform is returned. If the search cannot locate the next valid
+                            token namespace, an error is returned and the value of *Guid is undefined.
+
+  @retval  EFI_SUCCESS      The PCD service retrieved the value requested.
+  @retval  EFI_NOT_FOUND    The PCD service could not find the next valid token namespace.
+
+**/
+EFI_STATUS
+EFIAPI
+DxePcdGetNextTokenSpace (
+  IN OUT CONST EFI_GUID  **Guid
+  )
+{
+  UINTN     Idx;
+  UINTN     Idx2;
+  UINTN     Idx3;
+  UINTN     PeiTokenSpaceTableSize;
+  UINTN     DxeTokenSpaceTableSize;
+  EFI_GUID  **PeiTokenSpaceTable;
+  EFI_GUID  **DxeTokenSpaceTable;
+  BOOLEAN   Match;
+  BOOLEAN   PeiExMapTableEmpty;
+  BOOLEAN   DxeExMapTableEmpty;
+
+  ASSERT (Guid != NULL);
+
+  PeiExMapTableEmpty = mPeiExMapTableEmpty;
+  DxeExMapTableEmpty = mDxeExMapTableEmpty;
+
+  if (PeiExMapTableEmpty && DxeExMapTableEmpty) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (TmpTokenSpaceBuffer[0] == NULL) {
+    PeiTokenSpaceTableSize = 0;
+
+    if (!PeiExMapTableEmpty) {
+      PeiTokenSpaceTableSize = mPeiExMapppingTableSize / sizeof (DYNAMICEX_MAPPING);
+      PeiTokenSpaceTable     = GetDistinctTokenSpace (
+                                 &PeiTokenSpaceTableSize,
+                                 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->ExMapTableOffset),
+                                 (EFI_GUID *)((UINT8 *)mPcdDatabase.PeiDb + mPcdDatabase.PeiDb->GuidTableOffset)
+                                 );
+      CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID *) * PeiTokenSpaceTableSize);
+      TmpTokenSpaceBufferCount = PeiTokenSpaceTableSize;
+      FreePool (PeiTokenSpaceTable);
+    }
+
+    if (!DxeExMapTableEmpty) {
+      DxeTokenSpaceTableSize = mDxeExMapppingTableSize / sizeof (DYNAMICEX_MAPPING);
+      DxeTokenSpaceTable     = GetDistinctTokenSpace (
+                                 &DxeTokenSpaceTableSize,
+                                 (DYNAMICEX_MAPPING *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->ExMapTableOffset),
+                                 (EFI_GUID *)((UINT8 *)mPcdDatabase.DxeDb + mPcdDatabase.DxeDb->GuidTableOffset)
+                                 );
+
+      //
+      // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable
+      //
+      for (Idx2 = 0, Idx3 = PeiTokenSpaceTableSize; Idx2 < DxeTokenSpaceTableSize; Idx2++) {
+        Match = FALSE;
+        for (Idx = 0; Idx < PeiTokenSpaceTableSize; Idx++) {
+          if (CompareGuid (TmpTokenSpaceBuffer[Idx], DxeTokenSpaceTable[Idx2])) {
+            Match = TRUE;
+            break;
+          }
+        }
+
+        if (!Match) {
+          TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2];
+        }
+      }
+
+      TmpTokenSpaceBufferCount = Idx3;
+      FreePool (DxeTokenSpaceTable);
+    }
+  }
+
+  if (*Guid == NULL) {
+    *Guid = TmpTokenSpaceBuffer[0];
+    return EFI_SUCCESS;
+  }
+
+  for (Idx = 0; Idx < TmpTokenSpaceBufferCount; Idx++) {
+    if (CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) {
+      if (Idx == TmpTokenSpaceBufferCount - 1) {
+        //
+        // It has been the last token namespace.
+        //
+        *Guid = NULL;
+        return EFI_NOT_FOUND;
+      } else {
+        Idx++;
+        *Guid = TmpTokenSpaceBuffer[Idx];
+        return EFI_SUCCESS;
+      }
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
new file mode 100644
index 0000000000..044e46d0a7
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
@@ -0,0 +1,359 @@
+## @file
+# PCD DXE driver manage database contains all dynamic PCD entries and produce the implementation of PCD protocol.
+#
+# This version PCD DXE depends on the external PCD database binary file, not built in PCD data base.
+# There are two PCD Protocols as follows:
+#   1) PCD_PROTOCOL
+#      It is EDKII implementation which support Dynamic/DynamicEx type Pcds.
+#   2) EFI_PCD_PROTOCOL
+#      It is defined by PI specification 1.2, Vol 3 which only support dynamicEx
+#      type Pcd.
+#
+# For dynamicEx type PCD, it is compatible between PCD_PROTOCOL and EFI_PCD_PROTOCOL.
+# PCD DXE driver will produce above two protocols at same time.
+#
+# PCD database is generated as the separate binary image at build time. The binary image
+# will be intergrated into Firmware volume together with PCD driver.
+#
+# ////////////////////////////////////////////////////////////////////////////////
+# //                                                                            //
+# //                      Introduction of PCD database                          //
+# //                                                                            //
+# ////////////////////////////////////////////////////////////////////////////////
+#
+# 1, Introduction
+#    PCD database hold all dynamic type PCD information. The structure of PEI PCD
+#    database is generated by build tools according to dynamic PCD usage for
+#    specified platform.
+#
+# 2, Dynamic Type PCD
+#    Dynamic type PCD is used for the configuration/setting which value is determined
+#    dynamic. In contrast, the value of static type PCD (FeatureFlag, FixedPcd,
+#    PatchablePcd) is fixed in final generated FD image in build time.
+#
+#    2.1 The "dynamic" determination means one of below cases:
+#      a) The PCD setting value is produced by someone driver and consumed by
+#         other driver in execution time.
+#      b) The PCD setting value is set/get by user from FrontPage.
+#      c) The PCD setting value is produced by platform OEM vendor in specified area.
+#
+#    2.2 According to module distribution way, dynamic PCD could be classfied as:
+#      a) Dynamic:
+#         If module is released in source code and will be built with platform
+#         DSC, the dynamic PCD used by this module can be accessed as:
+#                 PcdGetxx(PcdSampleDynamicPcd);
+#         In building platform, build tools will translate PcdSampleDynamicPcd to
+#         pair of {Token Space Guid: Token Number} for this PCD.
+#      b) DynamicEx:
+#         If module is release as binary and will not pariticpate platform building,
+#         the dynamic PCD used by this module need be accessed as:
+#               PcdGetxxEx(gEfiMyTokenspaceGuid, PcdSampleDynamicPcd)
+#         Developer need explicity gives {Token Space Guid:Token Number} as parameter
+#         in writting source code.
+#
+#    2.3 According to PCD value's storage method, dynamic PCD could be classfied as:
+#      a) Default Storage:
+#         - The PCD value is stored in PCD database maintained by PCD driver in boot
+#           time memory.
+#         - This type is used for communication between PEIM/DXE driver, DXE/DXE
+#           driver. But all set/get value will be losted after boot-time memory
+#           is turn off.
+#         - [PcdsDynamicDefault] is used as section name for this type PCD in
+#           platform DSC file. [PcdsDynamicExDefault] is used for dynamicEx type PCD.
+#
+#      b) Variable Storage:
+#         - The PCD value is stored in variable area.
+#         - As default storage type, this type PCD could be used for PEI/DXE driver
+#           communication. But beside it, this type PCD could also be used to store
+#           the value associate with a HII setting via variable interface.
+#         - In PEI phase, the PCD value could only be got but can not be set due
+#           to variable area is readonly.
+#         - [PcdsDynamicHii] is used as section name for this type PCD in platform
+#           DSC file. [PcdsDynamicExHii] is for dynamicEx type PCD.
+#
+#      c) OEM specificed storage area:
+#         - The PCD value is stored in OEM specified area which base address is
+#           specified by PCD setting - PcdVpdBaseAddress64 or PcdVpdBaseAddress.
+#         - The area is read only for PEI and DXE phase.
+#         - [PcdsDynamicVpd] is used as section name for this type PCD in platform
+#           DSC file. [PcdsDynamicExVpd] is for dynamicex type PCD.
+#
+#    2.4 When and how to use dynamic PCD
+#      Module developer do not care the used PCD is dynamic or static when writting
+#      source code/INF. Dynamic PCD and dynamic type is pointed by platform integrator
+#      in platform DSC file. Please ref section 2.3 to get matching between dynamic
+#      PCD type and section name in DSC file.
+#
+# 3, PCD database:
+#    Although dynamic PCD could be in different storage type as above description,
+#    but the basic information and default value for all dynamic PCD is hold
+#    by PCD database maintained by PEI/DXE driver.
+#
+#    As the whole EFI BIOS boot path is divided into PEI/DXE phase, the PCD database
+#    also is divided into Pei/Dxe database maintaied by PcdPeim/PcdDxe driver separatly.
+#    To make PcdPeim's driver image smaller, PEI PCD database only hold all dynamic
+#    PCD information used in PEI phase or use in both PEI/DXE phase. And DXE PCD
+#    database contains all PCDs used in PEI/DXE phase in memory.
+#
+#    Build tool will generate PCD database into the separate binary file for
+#    PEI/DXE PCD driver according to dynamic PCD section in platform DSC file.
+#
+#    3.1 PcdPeim and PcdDxe
+#      PEI PCD database is maintained by PcdPeim driver run from flash. PcdPeim driver
+#      build guid hob in temporary memory and copy the binary data base from flash
+#      to temporary memory for PEI PCD database.
+#      DXE PCD database is maintained by PcdDxe driver.At entry point of PcdDxe driver,
+#      a new PCD database is allocated in boot-time memory which including all
+#      PEI PCD and DXE PCD entry.
+#
+#      Pcd driver should run as early as possible before any other driver access
+#      dynamic PCD's value. PEI/DXE "Apriori File" mechanism make it possible by
+#      making PcdPeim/PcdDxe as first dispatching driver in PEI/DXE phase.
+#
+#    3.2 Token space Guid/Token number, Platform token, Local token number
+#           Dynamic PCD
+#          +-----------+               +---------+
+#          |TokenSpace |               |Platform |
+#          |   Guid    |  build tool   | Token   |
+#          |    +      +-------------->| Number  |
+#          |  Token    |               +---------+`._
+#          |  Number   |                             `.
+#          +-----------+                               `.  +------+
+#                                                        `-|Local |
+#                                                          |Token |
+#                               DynamicEx PCD            ,-|Number|
+#                               +-----------+         ,-'  +------+
+#                               |TokenSpace |      ,-'
+#                               |   Guid    |  _,-'
+#                               |    +      +.'
+#                               |  Token    |
+#                               |  Number   |
+#                               +-----------+
+#
+#
+#      3.2.1 Pair of Token space guid + Token number
+#        Any type PCD is identified by pair of "TokenSpaceGuid + TokeNumber". But it
+#        is not easy maintained by PCD driver, and hashed token number will make
+#        searching slowly.
+#
+#      3.2.2 Platform Token Number
+#        "Platform token number" concept is introduced for mapping to a pair of
+#        "TokenSpaceGuid + TokenNumber". The platform token number is generated by
+#        build tool in autogen.h and all of them are continual in a platform scope
+#        started from 1.(0 meaning invalid internal token number)
+#        With auto-generated "platform token number", PcdGet(PcdSampleDynamicPcd)
+#        in source code is translated to LibPcdGet(_PCD_TOKEN_PcdSampleDynamicPcd)
+#        in autogen.h.
+#        Notes: The mapping between pair of "tokenspace guid + token number" and
+#        "internal token number" need build tool establish, so "platform token number"
+#        mechanism is not suitable for binary module which use DynamicEx type PCD.
+#        To access a dynamicEx type PCD, pair of "token space guid/token number" all need
+#        to be specificed for PcdSet/PcdGet accessing macro.
+#
+#        Platform Token Number is started from 1, and inceased continuous. From whole
+#        platform scope, there are two zones: PEI Zone and DXE Zone
+#                  |                      Platform Token Number
+#        ----------|----------------------------------------------------------------
+#        PEI Zone: |            1                 ~  PEI_LOCAL_TOKEN_NUMBER
+#        DXE Zone: | (PEI_LOCAL_TOKEN_NUMBER + 1) ~ (PEI_LOCAL_TOKEN_NUMBER + DXE_LOCAL_TOKEN_NUMBER)
+#
+#      3.2.3 Local Token Number
+#        To fast searching a PCD entry in PCD database, PCD driver translate
+#        platform token number to local token number via a mapping table.
+#        For binary DynamicEx type PCD, there is a another mapping table to translate
+#        "token space guid + token number" to local token number directly.
+#        Local token number is identifier for all internal interface in PCD PEI/DXE
+#        driver.
+#
+#        A local token number is a 32-bit value in following meaning:
+#         32 ------------- 28 ---------- 24 -------- 0
+#          | PCD type mask  | Datum Type  |  Offset  |
+#          +-----------------------------------------+
+#        where:
+#          PCd type mask: indicate Pcd type from following macro:
+#                         PCD_TYPE_DATA
+#                         PCD_TYPE_HII
+#                         PCD_TYPE_VPD
+#                         PCD_TYPE_STRING
+#          Datum Type   : indicate PCD vaue type from following macro:
+#                         PCD_DATUM_TYPE_POINTER
+#                         PCD_DATUM_TYPE_UINT8
+#                         PCD_DATUM_TYPE_UINT16
+#                         PCD_DATUM_TYPE_UINT32
+#                         PCD_DATUM_TYPE_UINT64
+#          Offset      : indicate the related offset of PCD value in PCD database array.
+#       Based on local token number, PCD driver could fast determine PCD type, value
+#       type and get PCD entry from PCD database.
+#
+#    3.3 PCD Database binary file
+#      PCD Database binary file will be created at build time as the standalone binary image.
+#      To understand the binary image layout, PCD Database C structure is still generated
+#      as comments by build tools in PCD driver's autogen.h/
+#      autogen.c file. In generated C structure, following information is stored:
+#      - ExMapTable: This table is used translate a binary dynamicex type PCD's
+#                    "tokenguid + token" to local token number.
+#      - LocalTokenNumberTable:
+#                    This table stores all local token number in array, use "Internal
+#                    token number" as array index to get PCD entry's offset fastly.
+#      - SizeTable:  This table stores the size information for all PCD entry.
+#      - GuidTable:  This table stores guid value for DynamicEx's token space,
+#                    HII type PCD's variable GUID.
+#      - SkuIdTable: TBD
+#      - SystemSkuId: TBD
+#      - PCD value structure:
+#                    Every PCD has a value record in PCD database. For different
+#                    datum type PCD has different record structure which will be
+#                    introduced in 3.3.1
+#
+#      In a PCD database structure, there are two major area: Init and UnInit.
+#      Init area is use stored above PCD internal structure such as ExMapTable,
+#      LocalTokenNumberTable etc and the (default) value of PCD which has default
+#      value specified in platform DSC file.
+#      Unint area is used stored the value of PCD which has no default value in
+#      platform DSC file, the value of NULL, 0 specified in platform DSC file can
+#      be seemed as "no default value".
+#
+#      3.3.1 Simple Sample PCD Database C Structure
+#        A general sample of PCD database structue is as follows:
+#        typedef struct _PCD_DATABASE {
+#          typedef struct _PCD_DATABASE_INIT {
+#            //===== Following is PCD database internal maintain structures
+#            DYNAMICEX_MAPPING ExMapTable[PEI_EXMAPPING_TABLE_SIZE];
+#            UINT32            LocalTokenNumberTable[PEI_LOCAL_TOKEN_NUMBER_TABLE_SIZE];
+#            GUID              GuidTable[PEI_GUID_TABLE_SIZE];
+#            SIZE_INFO         SizeTable[PEI_SIZE_TABLE_SIZE];
+#            UINT8             SkuIdTable[PEI_SKUID_TABLE_SIZE];
+#            SKU_ID            SystemSkuId;
+#
+#            //===== Following is value structure for PCD with default value
+#            ....
+#            ....
+#            ....
+#          } Init;
+#          typedef struct _PCD_DATABSE_UNINIT {
+#            //==== Following is value structure for PCD without default value
+#            ....
+#            ....
+#          } UnInit;
+#        }
+#
+#      3.3.2 PCD value structure in PCD database C structure
+#        The value's structure is generated by build tool in PCD database C structure.
+#        The PCDs in different datum type has different value structure.
+#
+#        3.3.2.1 UINT8/UINT16/UINT32/UINT64 datum type PCD
+#          The C structure for these datum type PCD is just a UINT8/UINT16/UINT32/UINT64
+#          data member in PCD database, For example:
+#          UINT16  PcdHardwareErrorRecordLevel_d3705011_bc19_4af7_be16_f68030378c15_VariableDefault_0;
+#          Above structure is generated by build tool, the member name is "PcdCName_Guidvalue"
+#          Member type is UINT16 according to PcdHardwareErrorRecordLevel declaration
+#          in DEC file.
+#
+#        3.3.2.2 VOID* datum type PCD
+#          The value of VOID* datum type PCD is a UINT8/UINT16 array in PCD database.
+#
+#          3.3.2.2.1 VOID* - string type
+#            If the default value for VOID* datum type PCD like L"xxx", the PCD is
+#            used for unicode string, and C structure of this datum type PCD is
+#            UINT16 string array in PCD database, for example:
+#            UINT16 StringTable[29];
+#            The number of 29 in above sample is max size of a unicode string.
+#
+#            If the default value for VOID* datum type PCD like "xxx", the PCD is
+#            used for ascii string, and C structure of this datum type PCD is
+#            UINT8 string array in PCD database, for example:
+#            UINT8 StringTable[20];
+#            The number of 20 in above sample is max size of a ascii string.
+#
+#          3.3.2.2.2 VOID* - byte array
+#            If the default value of VOID* datum type PCD like {'0x29', '0x01', '0xf2'}
+#            the PCD is used for byte array. The generated structrue is same as
+#            above ascii string table,
+#            UINT8 StringTable[13];
+#            The number of 13 in above sample is max size of byte array.
+#
+#      3.3.3 Some utility structures in PCD Database
+#        3.3.3.1 GuidTable
+#          GuidTable array is used to store all related GUID value in PCD database:
+#            - Variable GUID for HII type PCD
+#            - Token space GUID for dynamicex type PCD
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PcdDxe
+  MODULE_UNI_FILE                = PcdDxe.uni
+  FILE_GUID                      = 80CF7257-87AB-47f9-A3FE-D50B76D89541
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 4.0
+  PCD_IS_DRIVER                  = DXE_PCD_DRIVER
+  ENTRY_POINT                    = PcdDxeInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  Pcd.c
+  Service.c
+  Service.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ChachaniBoardPkg/Project.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+
+[LibraryClasses]
+  UefiRuntimeServicesTableLib
+  BaseMemoryLib
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  HobLib
+  UefiDriverEntryPoint
+  UefiLib
+  DebugLib
+  BaseLib
+  PcdLib
+  DxeServicesLib
+
+[Guids]
+  gPcdDataBaseHobGuid                           ## SOMETIMES_CONSUMES  ## HOB
+  gPcdDataBaseSignatureGuid                     ## CONSUMES  ## GUID  # PCD database signature GUID.
+  gEfiMdeModulePkgTokenSpaceGuid                ## SOMETIMES_CONSUMES  ## GUID
+  gEfiAmdAgesaModulePkgTokenSpaceGuid
+  gEfiAmdAgesaPkgTokenSpaceGuid
+  gAmdCpmPkgTokenSpaceGuid
+  gAmdFspPkgGuid
+
+[Protocols]
+  gPcdProtocolGuid                              ## PRODUCES
+  gEfiPcdProtocolGuid                           ## PRODUCES
+  gGetPcdInfoProtocolGuid                       ## SOMETIMES_PRODUCES
+  gEfiGetPcdInfoProtocolGuid                    ## SOMETIMES_PRODUCES
+  ## NOTIFY
+  ## SOMETIMES_CONSUMES
+  gEdkiiVariableLockProtocolGuid
+  gFspEfiPcdProtocolGuid
+  gFspEfiGetPcdInfoProtocolGuid
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress      ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress64    ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetNvStoreDefaultId ## SOMETIMES_CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection
+
+[Depex]
+  TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  PcdDxeExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c
new file mode 100644
index 0000000000..2a4045bd36
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c
@@ -0,0 +1,1876 @@
+/** @file
+  All Pcd Ppi services are implemented here.
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Service.h"
+
+extern EFI_GUID  gEfiAmdAgesaModulePkgTokenSpaceGuid;
+extern EFI_GUID  gEfiAmdAgesaPkgTokenSpaceGuid;
+extern EFI_GUID  gFspEfiGetPcdInfoPpiGuid;
+extern EFI_GUID  gFspEfiPeiPcdPpiGuid;
+
+STATIC
+BOOLEAN
+CheckPcdInFsp (
+  IN CONST EFI_GUID  *InputGuid
+  )
+{
+  if (  (FixedPcdGet8 (PcdFspModeSelection) == 0)                        // Dispatch mode
+     && (  CompareGuid (InputGuid, &gEfiAmdAgesaModulePkgTokenSpaceGuid) // AgesaModulePkg
+        || CompareGuid (InputGuid, &gEfiAmdAgesaPkgTokenSpaceGuid)       // AgesaPkg
+        || CompareGuid (InputGuid, &gAmdFspPkgGuid)                      // FspPkg
+        || CompareGuid (InputGuid, &gAmdCpmPkgTokenSpaceGuid)))          // AmdCpmPkg
+  {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+///
+/// Instance of PCD_PPI protocol is EDKII native implementation.
+/// This protocol instance support dynamic and dynamicEx type PCDs.
+///
+PCD_PPI  mPcdPpiInstance = {
+  PeiPcdSetSku,
+
+  PeiPcdGet8,
+  PeiPcdGet16,
+  PeiPcdGet32,
+  PeiPcdGet64,
+  PeiPcdGetPtr,
+  PeiPcdGetBool,
+  PeiPcdGetSize,
+
+  PeiPcdGet8Ex,
+  PeiPcdGet16Ex,
+  PeiPcdGet32Ex,
+  PeiPcdGet64Ex,
+  PeiPcdGetPtrEx,
+  PeiPcdGetBoolEx,
+  PeiPcdGetSizeEx,
+
+  PeiPcdSet8,
+  PeiPcdSet16,
+  PeiPcdSet32,
+  PeiPcdSet64,
+  PeiPcdSetPtr,
+  PeiPcdSetBool,
+
+  PeiPcdSet8Ex,
+  PeiPcdSet16Ex,
+  PeiPcdSet32Ex,
+  PeiPcdSet64Ex,
+  PeiPcdSetPtrEx,
+  PeiPcdSetBoolEx,
+
+  PeiRegisterCallBackOnSet,
+  PcdUnRegisterCallBackOnSet,
+  PeiPcdGetNextToken,
+  PeiPcdGetNextTokenSpace
+};
+
+///
+/// Instance of EFI_PEI_PCD_PPI which is defined in PI 1.2 Vol 3.
+/// This PPI instance only support dyanmicEx type PCD.
+///
+EFI_PEI_PCD_PPI  mEfiPcdPpiInstance = {
+  PeiPcdSetSku,
+
+  PeiPcdGet8Ex,
+  PeiPcdGet16Ex,
+  PeiPcdGet32Ex,
+  PeiPcdGet64Ex,
+  PeiPcdGetPtrEx,
+  PeiPcdGetBoolEx,
+  PeiPcdGetSizeEx,
+  PeiPcdSet8Ex,
+  PeiPcdSet16Ex,
+  PeiPcdSet32Ex,
+  PeiPcdSet64Ex,
+  PeiPcdSetPtrEx,
+  PeiPcdSetBoolEx,
+  (EFI_PEI_PCD_PPI_CALLBACK_ON_SET)PeiRegisterCallBackOnSet,
+  (EFI_PEI_PCD_PPI_CANCEL_CALLBACK)PcdUnRegisterCallBackOnSet,
+  PeiPcdGetNextToken,
+  PeiPcdGetNextTokenSpace
+};
+
+///
+/// Instance of GET_PCD_INFO_PPI protocol is EDKII native implementation.
+/// This protocol instance support dynamic and dynamicEx type PCDs.
+///
+GET_PCD_INFO_PPI  mGetPcdInfoInstance = {
+  PeiGetPcdInfoGetInfo,
+  PeiGetPcdInfoGetInfoEx,
+  PeiGetPcdInfoGetSku
+};
+
+///
+/// Instance of EFI_GET_PCD_INFO_PPI which is defined in PI 1.2.1 Vol 3.
+/// This PPI instance only support dyanmicEx type PCD.
+///
+EFI_GET_PCD_INFO_PPI  mEfiGetPcdInfoInstance = {
+  PeiGetPcdInfoGetInfoEx,
+  PeiGetPcdInfoGetSku
+};
+
+EFI_PEI_PPI_DESCRIPTOR  mPpiList[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI,
+    &gPcdPpiGuid,
+    &mPcdPpiInstance
+  },
+  {
+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+    &gEfiPeiPcdPpiGuid,
+    &mEfiPcdPpiInstance
+  }
+};
+
+EFI_PEI_PPI_DESCRIPTOR  mPpiList2[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI,
+    &gGetPcdInfoPpiGuid,
+    &mGetPcdInfoInstance
+  },
+  {
+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+    &gEfiGetPcdInfoPpiGuid,
+    &mEfiGetPcdInfoInstance
+  }
+};
+
+/**
+  Callback on SET PcdSetNvStoreDefaultId
+
+  Once PcdSetNvStoreDefaultId is set, the default NV storage will be found from
+  PcdNvStoreDefaultValueBuffer, and built into VariableHob.
+
+  @param[in]      CallBackGuid  The PCD token GUID being set.
+  @param[in]      CallBackToken The PCD token number being set.
+  @param[in, out] TokenData     A pointer to the token data being set.
+  @param[in]      TokenDataSize The size, in bytes, of the data being set.
+
+**/
+VOID
+EFIAPI
+PcdSetNvStoreDefaultIdCallBack (
+  IN CONST EFI_GUID  *CallBackGuid  OPTIONAL,
+  IN       UINTN     CallBackToken,
+  IN OUT   VOID      *TokenData,
+  IN       UINTN     TokenDataSize
+  )
+{
+  EFI_STATUS             Status;
+  UINT16                 DefaultId;
+  SKU_ID                 SkuId;
+  UINTN                  FullSize;
+  UINTN                  Index;
+  UINT8                  *DataBuffer;
+  UINT8                  *VarStoreHobData;
+  UINT8                  *BufferEnd;
+  BOOLEAN                IsFound;
+  VARIABLE_STORE_HEADER  *NvStoreBuffer;
+  PCD_DEFAULT_DATA       *DataHeader;
+  PCD_DEFAULT_INFO       *DefaultInfo;
+  PCD_DATA_DELTA         *DeltaData;
+
+  DefaultId = *(UINT16 *)TokenData;
+  SkuId     = GetPcdDatabase ()->SystemSkuId;
+  IsFound   = FALSE;
+
+  if (PeiPcdGetSizeEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer)) > sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
+    DataBuffer = (UINT8 *)PeiPcdGetPtrEx (&gEfiMdeModulePkgTokenSpaceGuid, PcdToken (PcdNvStoreDefaultValueBuffer));
+    FullSize   = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)DataBuffer)->Length;
+    DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));
+    //
+    // The first section data includes NV storage default setting.
+    //
+    NvStoreBuffer   = (VARIABLE_STORE_HEADER *)((UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);
+    VarStoreHobData = (UINT8 *)BuildGuidHob (&NvStoreBuffer->Signature, NvStoreBuffer->Size);
+    ASSERT (VarStoreHobData != NULL);
+    CopyMem (VarStoreHobData, NvStoreBuffer, NvStoreBuffer->Size);
+    //
+    // Find the matched SkuId and DefaultId in the first section
+    //
+    DefaultInfo = &(DataHeader->DefaultInfo[0]);
+    BufferEnd   = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
+    while ((UINT8 *)DefaultInfo < BufferEnd) {
+      if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == SkuId)) {
+        IsFound = TRUE;
+        break;
+      }
+
+      DefaultInfo++;
+    }
+
+    //
+    // Find the matched SkuId and DefaultId in the remaining section
+    //
+    Index      = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));
+    DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);
+    while (!IsFound && Index < FullSize && DataHeader->DataSize != 0xFFFFFFFF) {
+      DefaultInfo = &(DataHeader->DefaultInfo[0]);
+      BufferEnd   = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
+      while ((UINT8 *)DefaultInfo < BufferEnd) {
+        if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == SkuId)) {
+          IsFound = TRUE;
+          break;
+        }
+
+        DefaultInfo++;
+      }
+
+      if (IsFound) {
+        DeltaData = (PCD_DATA_DELTA *)BufferEnd;
+        BufferEnd = (UINT8 *)DataHeader + DataHeader->DataSize;
+        while ((UINT8 *)DeltaData < BufferEnd) {
+          *(VarStoreHobData + DeltaData->Offset) = (UINT8)DeltaData->Value;
+          DeltaData++;
+        }
+
+        break;
+      }
+
+      Index      = (Index + DataHeader->DataSize + 7) & (~7);
+      DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);
+    }
+  }
+
+  Status = PcdUnRegisterCallBackOnSet (
+             &gEfiMdeModulePkgTokenSpaceGuid,
+             PcdToken (PcdSetNvStoreDefaultId),
+             PcdSetNvStoreDefaultIdCallBack
+             );
+  ASSERT_EFI_ERROR (Status);
+}
+
+/**
+  Report Pei PCD database of all SKUs as Guid HOB so that DxePcd can access it.
+
+  @param PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+  @param NotifyDescriptor  Address of the notification descriptor data structure.
+  @param Ppi               Address of the PPI that was installed.
+
+  @retval EFI_SUCCESS      Successfully update the Boot records.
+**/
+EFI_STATUS
+EFIAPI
+EndOfPeiSignalPpiNotifyCallback (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  PEI_PCD_DATABASE     *Database;
+  EFI_BOOT_MODE        BootMode;
+  EFI_STATUS           Status;
+  UINTN                Instance;
+  EFI_PEI_FV_HANDLE    VolumeHandle;
+  EFI_PEI_FILE_HANDLE  FileHandle;
+  VOID                 *PcdDb;
+  UINT32               Length;
+  PEI_PCD_DATABASE     *PeiPcdDb;
+
+  Status = PeiServicesGetBootMode (&BootMode);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Don't need to report it on S3 boot.
+  //
+  if (BootMode == BOOT_ON_S3_RESUME) {
+    return EFI_SUCCESS;
+  }
+
+  PeiPcdDb = GetPcdDatabase ();
+  if (PeiPcdDb->SystemSkuId != (SKU_ID)0) {
+    //
+    // SkuId has been set. Don't need to report it to DXE phase.
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Get full PCD database from PcdPeim FileHandle
+  //
+  Instance   = 0;
+  FileHandle = NULL;
+  while (TRUE) {
+    //
+    // Traverse all firmware volume instances
+    //
+    Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);
+    //
+    // Error should not happen
+    //
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // Find PcdDb file from the beginning in this firmware volume.
+    //
+    FileHandle = NULL;
+    Status     = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle);
+    if (!EFI_ERROR (Status)) {
+      //
+      // Find PcdPeim FileHandle in this volume
+      //
+      break;
+    }
+
+    //
+    // We cannot find PcdPeim in this firmware volume, then search the next volume.
+    //
+    Instance++;
+  }
+
+  //
+  // Find PEI PcdDb and Build second PcdDB GuidHob
+  //
+  Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);
+  ASSERT_EFI_ERROR (Status);
+  Length   = PeiPcdDb->LengthForAllSkus;
+  Database = BuildGuidHob (&gPcdDataBaseHobGuid, Length);
+  CopyMem (Database, PcdDb, Length);
+
+  return EFI_SUCCESS;
+}
+
+EFI_PEI_NOTIFY_DESCRIPTOR  mEndOfPeiSignalPpiNotifyList[] = {
+  {
+    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+    &gEfiEndOfPeiSignalPpiGuid,
+    EndOfPeiSignalPpiNotifyCallback
+  }
+};
+
+/**
+  Main entry for PCD PEIM driver.
+
+  This routine initialize the PCD database for PEI phase and install PCD_PPI/EFI_PEI_PCD_PPI.
+
+  @param  FileHandle  Handle of the file being invoked.
+  @param  PeiServices Describes the list of possible PEI Services.
+
+  @return Status of install PCD_PPI
+
+**/
+EFI_STATUS
+EFIAPI
+PcdPeimInit (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = PeiServicesRegisterForShadow (FileHandle);
+  if (Status == EFI_ALREADY_STARTED) {
+    //
+    // This is now starting in memory, the second time starting.
+    //
+    EFI_PEI_PPI_DESCRIPTOR  *OldPpiList;
+    EFI_PEI_PPI_DESCRIPTOR  *OldPpiList2;
+    VOID                    *Ppi;
+    VOID                    *Ppi2;
+
+    OldPpiList = NULL;
+    Status     = PeiServicesLocatePpi (
+                   &gPcdPpiGuid,
+                   0,
+                   &OldPpiList,
+                   &Ppi
+                   );
+    ASSERT_EFI_ERROR (Status);
+
+    if (OldPpiList != NULL) {
+      Status = PeiServicesReInstallPpi (OldPpiList, &mPpiList[0]);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    OldPpiList2 = NULL;
+    Status      = PeiServicesLocatePpi (
+                    &gGetPcdInfoPpiGuid,
+                    0,
+                    &OldPpiList2,
+                    &Ppi2
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    if (OldPpiList2 != NULL) {
+      Status = PeiServicesReInstallPpi (OldPpiList2, &mPpiList2[0]);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    OldPpiList = NULL;
+    Status     = PeiServicesLocatePpi (
+                   &gEfiPeiPcdPpiGuid,
+                   0,
+                   &OldPpiList,
+                   &Ppi
+                   );
+    ASSERT_EFI_ERROR (Status);
+
+    if (OldPpiList != NULL) {
+      Status = PeiServicesReInstallPpi (OldPpiList, &mPpiList[1]);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    OldPpiList2 = NULL;
+    Status      = PeiServicesLocatePpi (
+                    &gEfiGetPcdInfoPpiGuid,
+                    0,
+                    &OldPpiList2,
+                    &Ppi2
+                    );
+    ASSERT_EFI_ERROR (Status);
+
+    if (OldPpiList2 != NULL) {
+      Status = PeiServicesReInstallPpi (OldPpiList2, &mPpiList2[1]);
+      ASSERT_EFI_ERROR (Status);
+    }
+
+    return Status;
+  }
+
+  BuildPcdDatabase (FileHandle);
+
+  //
+  // Install PCD_PPI and EFI_PEI_PCD_PPI.
+  //
+  Status = PeiServicesInstallPpi (&mPpiList[0]);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Install GET_PCD_INFO_PPI and EFI_GET_PCD_INFO_PPI.
+  //
+  Status = PeiServicesInstallPpi (&mPpiList2[0]);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = PeiServicesNotifyPpi (&mEndOfPeiSignalPpiNotifyList[0]);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = PeiRegisterCallBackOnSet (
+             &gEfiMdeModulePkgTokenSpaceGuid,
+             PcdToken (PcdSetNvStoreDefaultId),
+             PcdSetNvStoreDefaultIdCallBack
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Retrieve additional information associated with a PCD token in the default token space.
+
+  This includes information such as the type of value the TokenNumber is associated with as well as possible
+  human readable name that is associated with the token.
+
+  @param[in]    TokenNumber The PCD token number.
+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.
+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+  @retval  EFI_SUCCESS      The PCD information was returned successfully.
+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+PeiGetPcdInfoGetInfo (
+  IN        UINTN         TokenNumber,
+  OUT       EFI_PCD_INFO  *PcdInfo
+  )
+{
+  return PeiGetPcdInfo (NULL, TokenNumber, PcdInfo);
+}
+
+/**
+  Retrieve additional information associated with a PCD token.
+
+  This includes information such as the type of value the TokenNumber is associated with as well as possible
+  human readable name that is associated with the token.
+
+  @param[in]    Guid        The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]    TokenNumber The PCD token number.
+  @param[out]   PcdInfo     The returned information associated with the requested TokenNumber.
+                            The caller is responsible for freeing the buffer that is allocated by callee for PcdInfo->PcdName.
+
+  @retval  EFI_SUCCESS      The PCD information was returned successfully.
+  @retval  EFI_NOT_FOUND    The PCD service could not find the requested token number.
+**/
+EFI_STATUS
+EFIAPI
+PeiGetPcdInfoGetInfoEx (
+  IN CONST  EFI_GUID      *Guid,
+  IN        UINTN         TokenNumber,
+  OUT       EFI_PCD_INFO  *PcdInfo
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_GET_PCD_INFO_PPI  *FspPcdGetInfoPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiGetPcdInfoPpiGuid, 0, NULL, (VOID **)&FspPcdGetInfoPpi);
+    ASSERT (FspPcdGetInfoPpi != NULL);
+    return FspPcdGetInfoPpi->GetInfo (Guid, TokenNumber, PcdInfo);
+  }
+
+  return PeiGetPcdInfo (Guid, TokenNumber, PcdInfo);
+}
+
+/**
+  Retrieve the currently set SKU Id.
+
+  @return   The currently set SKU Id. If the platform has not set at a SKU Id, then the
+            default SKU Id value of 0 is returned. If the platform has set a SKU Id, then the currently set SKU
+            Id is returned.
+**/
+UINTN
+EFIAPI
+PeiGetPcdInfoGetSku (
+  VOID
+  )
+{
+  return (UINTN)GetPcdDatabase ()->SystemSkuId;
+}
+
+/**
+  Sets the SKU value for subsequent calls to set or get PCD token values.
+
+  SetSku() sets the SKU Id to be used for subsequent calls to set or get PCD values.
+  SetSku() is normally called only once by the system.
+
+  For each item (token), the database can hold a single value that applies to all SKUs,
+  or multiple values, where each value is associated with a specific SKU Id. Items with multiple,
+  SKU-specific values are called SKU enabled.
+
+  The SKU Id of zero is reserved as a default.
+  For tokens that are not SKU enabled, the system ignores any set SKU Id and works with the
+  single value for that token. For SKU-enabled tokens, the system will use the SKU Id set by the
+  last call to SetSku(). If no SKU Id is set or the currently set SKU Id isn't valid for the specified token,
+  the system uses the default SKU Id. If the system attempts to use the default SKU Id and no value has been
+  set for that Id, the results are unpredictable.
+
+  @param[in]  SkuId The SKU value that will be used when the PCD service will retrieve and
+              set values associated with a PCD token.
+
+**/
+VOID
+EFIAPI
+PeiPcdSetSku (
+  IN  UINTN  SkuId
+  )
+{
+  PEI_PCD_DATABASE        *PeiPcdDb;
+  SKU_ID                  *SkuIdTable;
+  UINTN                   Index;
+  EFI_STATUS              Status;
+  UINTN                   Instance;
+  EFI_PEI_FV_HANDLE       VolumeHandle;
+  EFI_PEI_FILE_HANDLE     FileHandle;
+  VOID                    *PcdDb;
+  UINT32                  Length;
+  PCD_DATABASE_SKU_DELTA  *SkuDelta;
+  PCD_DATA_DELTA          *SkuDeltaData;
+
+  DEBUG ((DEBUG_INFO, "PcdPei - SkuId 0x%lx is to be set.\n", (SKU_ID)SkuId));
+
+  PeiPcdDb = GetPcdDatabase ();
+
+  if (SkuId == PeiPcdDb->SystemSkuId) {
+    //
+    // The input SKU Id is equal to current SKU Id, return directly.
+    //
+    DEBUG ((DEBUG_INFO, "PcdPei - SkuId is same to current system Sku.\n"));
+    return;
+  }
+
+  if (PeiPcdDb->SystemSkuId != (SKU_ID)0) {
+    DEBUG ((DEBUG_ERROR, "PcdPei - The SKU Id could be changed only once."));
+    DEBUG ((
+      DEBUG_ERROR,
+      "PcdPei - The SKU Id was set to 0x%lx already, it could not be set to 0x%lx any more.",
+      PeiPcdDb->SystemSkuId,
+      (SKU_ID)SkuId
+      ));
+    ASSERT (FALSE);
+    return;
+  }
+
+  SkuIdTable = (SKU_ID *)((UINT8 *)PeiPcdDb + PeiPcdDb->SkuIdTableOffset);
+  for (Index = 0; Index < SkuIdTable[0]; Index++) {
+    if (SkuId == SkuIdTable[Index + 1]) {
+      DEBUG ((DEBUG_INFO, "PcdPei - SkuId is found in SkuId table.\n"));
+      break;
+    }
+  }
+
+  if (Index < SkuIdTable[0]) {
+    //
+    // Get full PCD database from PcdPeim FileHandle
+    //
+    Instance   = 0;
+    FileHandle = NULL;
+    while (TRUE) {
+      //
+      // Traverse all firmware volume instances
+      //
+      Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);
+      //
+      // Error should not happen
+      //
+      ASSERT_EFI_ERROR (Status);
+
+      //
+      // Find PcdDb file from the beginning in this firmware volume.
+      //
+      FileHandle = NULL;
+      Status     = PeiServicesFfsFindFileByName (&gEfiCallerIdGuid, VolumeHandle, &FileHandle);
+      if (!EFI_ERROR (Status)) {
+        //
+        // Find PcdPeim FileHandle in this volume
+        //
+        break;
+      }
+
+      //
+      // We cannot find PcdPeim in this firmware volume, then search the next volume.
+      //
+      Instance++;
+    }
+
+    //
+    // Find the delta data between the different Skus
+    //
+    Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, FileHandle, &PcdDb);
+    ASSERT_EFI_ERROR (Status);
+    Length   = PeiPcdDb->LengthForAllSkus;
+    Index    = (PeiPcdDb->Length + 7) & (~7);
+    SkuDelta = NULL;
+    while (Index < Length) {
+      SkuDelta = (PCD_DATABASE_SKU_DELTA *)((UINT8 *)PcdDb + Index);
+      if ((SkuDelta->SkuId == SkuId) && (SkuDelta->SkuIdCompared == 0)) {
+        break;
+      }
+
+      Index = (Index + SkuDelta->Length + 7) & (~7);
+    }
+
+    //
+    // Patch the delta data into current PCD database
+    //
+    if ((Index < Length) && (SkuDelta != NULL)) {
+      SkuDeltaData = (PCD_DATA_DELTA *)(SkuDelta + 1);
+      while ((UINT8 *)SkuDeltaData < (UINT8 *)SkuDelta + SkuDelta->Length) {
+        *((UINT8 *)PeiPcdDb + SkuDeltaData->Offset) = (UINT8)SkuDeltaData->Value;
+        SkuDeltaData++;
+      }
+
+      PeiPcdDb->SystemSkuId = (SKU_ID)SkuId;
+      DEBUG ((DEBUG_INFO, "PcdPei - Set current SKU Id to 0x%lx.\n", (SKU_ID)SkuId));
+      return;
+    }
+  }
+
+  //
+  // Invalid input SkuId, the default SKU Id will be still used for the system.
+  //
+  DEBUG ((DEBUG_ERROR, "PcdPei - Invalid input SkuId, the default SKU Id will be still used.\n"));
+
+  return;
+}
+
+/**
+  Retrieves an 8-bit value for a given PCD token.
+
+  Retrieves the current byte-sized value for a PCD token number.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The UINT8 value.
+
+**/
+UINT8
+EFIAPI
+PeiPcdGet8 (
+  IN UINTN  TokenNumber
+  )
+{
+  return *((UINT8 *)GetWorker (TokenNumber, sizeof (UINT8)));
+}
+
+/**
+  Retrieves an 16-bit value for a given PCD token.
+
+  Retrieves the current 16-bits value for a PCD token number.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The UINT16 value.
+
+**/
+UINT16
+EFIAPI
+PeiPcdGet16 (
+  IN UINTN  TokenNumber
+  )
+{
+  return ReadUnaligned16 (GetWorker (TokenNumber, sizeof (UINT16)));
+}
+
+/**
+  Retrieves an 32-bit value for a given PCD token.
+
+  Retrieves the current 32-bits value for a PCD token number.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The UINT32 value.
+
+**/
+UINT32
+EFIAPI
+PeiPcdGet32 (
+  IN UINTN  TokenNumber
+  )
+{
+  return ReadUnaligned32 (GetWorker (TokenNumber, sizeof (UINT32)));
+}
+
+/**
+  Retrieves an 64-bit value for a given PCD token.
+
+  Retrieves the current 64-bits value for a PCD token number.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The UINT64 value.
+
+**/
+UINT64
+EFIAPI
+PeiPcdGet64 (
+  IN UINTN  TokenNumber
+  )
+{
+  return ReadUnaligned64 (GetWorker (TokenNumber, sizeof (UINT64)));
+}
+
+/**
+  Retrieves a pointer to a value for a given PCD token.
+
+  Retrieves the current pointer to the buffer for a PCD token number.
+  Do not make any assumptions about the alignment of the pointer that
+  is returned by this function call.  If the TokenNumber is invalid,
+  the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The pointer to the buffer to be retrieved.
+
+**/
+VOID *
+EFIAPI
+PeiPcdGetPtr (
+  IN UINTN  TokenNumber
+  )
+{
+  return GetWorker (TokenNumber, 0);
+}
+
+/**
+  Retrieves a Boolean value for a given PCD token.
+
+  Retrieves the current boolean value for a PCD token number.
+  Do not make any assumptions about the alignment of the pointer that
+  is returned by this function call.  If the TokenNumber is invalid,
+  the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The Boolean value.
+
+**/
+BOOLEAN
+EFIAPI
+PeiPcdGetBool (
+  IN UINTN  TokenNumber
+  )
+{
+  return *((BOOLEAN *)GetWorker (TokenNumber, sizeof (BOOLEAN)));
+}
+
+/**
+  Retrieves the size of the value for a given PCD token.
+
+  Retrieves the current size of a particular PCD token.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  TokenNumber The PCD token number.
+
+  @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+PeiPcdGetSize (
+  IN UINTN  TokenNumber
+  )
+{
+  PEI_PCD_DATABASE  *PeiPcdDb;
+  UINTN             Size;
+  UINTN             MaxSize;
+  UINT32            LocalTokenCount;
+
+  PeiPcdDb        = GetPcdDatabase ();
+  LocalTokenCount = PeiPcdDb->LocalTokenCount;
+  //
+  // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
+  // We have to decrement TokenNumber by 1 to make it usable
+  // as the array index.
+  //
+  TokenNumber--;
+
+  // EBC compiler is very choosy. It may report warning about comparison
+  // between UINTN and 0 . So we add 1 in each size of the
+  // comparison.
+  ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));
+
+  Size = (*((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber) & PCD_DATUM_TYPE_ALL_SET) >> PCD_DATUM_TYPE_SHIFT;
+
+  if (Size == 0) {
+    //
+    // For pointer type, we need to scan the SIZE_TABLE to get the current size.
+    //
+    return GetPtrTypeSize (TokenNumber, &MaxSize, PeiPcdDb);
+  } else {
+    return Size;
+  }
+}
+
+/**
+  Retrieves an 8-bit value for a given PCD token.
+
+  Retrieves the 8-bit value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid              The token space for the token number.
+  @param[in]  ExTokenNumber     The PCD token number.
+
+  @return The size 8-bit value for the PCD token.
+
+**/
+UINT8
+EFIAPI
+PeiPcdGet8Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->Get8 (Guid, ExTokenNumber);
+  }
+
+  return *((UINT8 *)ExGetWorker (Guid, ExTokenNumber, sizeof (UINT8)));
+}
+
+/**
+  Retrieves an 16-bit value for a given PCD token.
+
+  Retrieves the 16-bit value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid          The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size 16-bit value for the PCD token.
+
+**/
+UINT16
+EFIAPI
+PeiPcdGet16Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->Get16 (Guid, ExTokenNumber);
+  }
+
+  return ReadUnaligned16 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT16)));
+}
+
+/**
+  Retrieves an 32-bit value for a given PCD token.
+
+  Retrieves the 32-bit value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size 32-bit value for the PCD token.
+
+**/
+UINT32
+EFIAPI
+PeiPcdGet32Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->Get32 (Guid, ExTokenNumber);
+  }
+
+  return ReadUnaligned32 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT32)));
+}
+
+/**
+  Retrieves an 64-bit value for a given PCD token.
+
+  Retrieves the 64-bit value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size 64-bit value for the PCD token.
+
+**/
+UINT64
+EFIAPI
+PeiPcdGet64Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->Get64 (Guid, ExTokenNumber);
+  }
+
+  return ReadUnaligned64 (ExGetWorker (Guid, ExTokenNumber, sizeof (UINT64)));
+}
+
+/**
+  Retrieves a pointer to a value for a given PCD token.
+
+  Retrieves the current pointer to the buffer for a PCD token number.
+  Do not make any assumptions about the alignment of the pointer that
+  is returned by this function call.  If the TokenNumber is invalid,
+  the results are unpredictable.
+
+  @param[in]  Guid          The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The pointer to the buffer to be retrieved.
+
+**/
+VOID *
+EFIAPI
+PeiPcdGetPtrEx (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->GetPtr (Guid, ExTokenNumber);
+  }
+
+  return ExGetWorker (Guid, ExTokenNumber, 0);
+}
+
+/**
+  Retrieves an Boolean value for a given PCD token.
+
+  Retrieves the Boolean value of a particular PCD token.
+  If the TokenNumber is invalid or the token space
+  specified by Guid does not exist, the results are
+  unpredictable.
+
+  @param[in]  Guid          The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size Boolean value for the PCD token.
+
+**/
+BOOLEAN
+EFIAPI
+PeiPcdGetBoolEx (
+  IN CONST  EFI_GUID  *Guid,
+  IN UINTN            ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->GetBool (Guid, ExTokenNumber);
+  }
+
+  return *((BOOLEAN *)ExGetWorker (Guid, ExTokenNumber, sizeof (BOOLEAN)));
+}
+
+/**
+  Retrieves the size of the value for a given PCD token.
+
+  Retrieves the current size of a particular PCD token.
+  If the TokenNumber is invalid, the results are unpredictable.
+
+  @param[in]  Guid          The token space for the token number.
+  @param[in]  ExTokenNumber The PCD token number.
+
+  @return The size of the value for the PCD token.
+
+**/
+UINTN
+EFIAPI
+PeiPcdGetSizeEx (
+  IN CONST  EFI_GUID  *Guid,
+  IN UINTN            ExTokenNumber
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->GetSize (Guid, ExTokenNumber);
+  }
+
+  return PeiPcdGetSize (GetExPcdTokenNumber (Guid, ExTokenNumber));
+}
+
+/**
+  Sets an 8-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet8 (
+  IN UINTN  TokenNumber,
+  IN UINT8  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 16-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet16 (
+  IN UINTN   TokenNumber,
+  IN UINT16  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 32-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet32 (
+  IN UINTN   TokenNumber,
+  IN UINT32  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 64-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet64 (
+  IN UINTN   TokenNumber,
+  IN UINT64  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets a value of a specified size for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in, out] SizeOfBuffer A pointer to the length of the value being set for the PCD token.
+                              On input, if the SizeOfValue is greater than the maximum size supported
+                              for this TokenNumber then the output value of SizeOfValue will reflect
+                              the maximum size supported for this TokenNumber.
+  @param[in]  Buffer The buffer to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetPtr (
+  IN      UINTN  TokenNumber,
+  IN OUT  UINTN  *SizeOfBuffer,
+  IN      VOID   *Buffer
+  )
+{
+  return SetWorker (TokenNumber, Buffer, SizeOfBuffer, TRUE);
+}
+
+/**
+  Sets an Boolean value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  TokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetBool (
+  IN UINTN    TokenNumber,
+  IN BOOLEAN  Value
+  )
+{
+  return SetValueWorker (TokenNumber, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 8-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid          The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  Value         The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet8Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN UINT8           Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->Set8 (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 16-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  Value The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet16Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN UINT16          Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->Set16 (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 32-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid          The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  Value         The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet32Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN UINT32          Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->Set32 (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Sets an 64-bit value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]  Guid          The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  Value         The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSet64Ex (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN UINT64          Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->Set64 (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Sets a value of a specified size for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param[in]        Guid            The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]        ExTokenNumber   The PCD token number.
+  @param[in, out]   SizeOfBuffer    A pointer to the length of the value being set for the PCD token.
+                                    On input, if the SizeOfValue is greater than the maximum size supported
+                                    for this TokenNumber then the output value of SizeOfValue will reflect
+                                    the maximum size supported for this TokenNumber.
+  @param[in]        Value           The buffer to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetPtrEx (
+  IN     CONST EFI_GUID  *Guid,
+  IN     UINTN           ExTokenNumber,
+  IN OUT UINTN           *SizeOfBuffer,
+  IN     VOID            *Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->SetPtr (Guid, ExTokenNumber, SizeOfBuffer, Value);
+  }
+
+  return ExSetWorker (ExTokenNumber, Guid, Value, SizeOfBuffer, TRUE);
+}
+
+/**
+  Sets an Boolean value for a given PCD token.
+
+  When the PCD service sets a value, it will check to ensure that the
+  size of the value being set is compatible with the Token's existing definition.
+  If it is not, an error will be returned.
+
+  @param [in]  Guid          The 128-bit unique value that designates the namespace from which to extract the value.
+  @param [in]  ExTokenNumber The PCD token number.
+  @param [in]  Value         The value to set for the PCD token.
+
+  @retval EFI_SUCCESS  Procedure returned successfully.
+  @retval EFI_INVALID_PARAMETER The PCD service determined that the size of the data
+                                  being set was incompatible with a call to this function.
+                                  Use GetSize() to retrieve the size of the target data.
+  @retval EFI_NOT_FOUND The PCD service could not find the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdSetBoolEx (
+  IN CONST EFI_GUID  *Guid,
+  IN UINTN           ExTokenNumber,
+  IN BOOLEAN         Value
+  )
+{
+  if (CheckPcdInFsp (Guid)) {
+    EFI_PEI_PCD_PPI  *FspPcdPpi = NULL;
+    PeiServicesLocatePpi (&gFspEfiPeiPcdPpiGuid, 0, NULL, (VOID **)&FspPcdPpi);
+    ASSERT (FspPcdPpi != NULL);
+    return FspPcdPpi->SetBool (Guid, ExTokenNumber, Value);
+  }
+
+  return ExSetValueWorker (ExTokenNumber, Guid, &Value, sizeof (Value));
+}
+
+/**
+  Specifies a function to be called anytime the value of a designated token is changed.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+  @retval EFI_SUCCESS  The PCD service has successfully established a call event
+                        for the CallBackToken requested.
+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiRegisterCallBackOnSet (
+  IN  CONST EFI_GUID    *Guid  OPTIONAL,
+  IN  UINTN             ExTokenNumber,
+  IN  PCD_PPI_CALLBACK  CallBackFunction
+  )
+{
+  if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (CallBackFunction == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, TRUE);
+}
+
+/**
+  Cancels a previously set callback function for a particular PCD token number.
+
+  @param[in]  Guid The 128-bit unique value that designates the namespace from which to extract the value.
+  @param[in]  ExTokenNumber The PCD token number.
+  @param[in]  CallBackFunction The function prototype called when the value associated with the CallBackToken is set.
+
+  @retval EFI_SUCCESS  The PCD service has successfully established a call event
+                        for the CallBackToken requested.
+  @retval EFI_NOT_FOUND The PCD service could not find the referenced token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PcdUnRegisterCallBackOnSet (
+  IN  CONST EFI_GUID    *Guid  OPTIONAL,
+  IN  UINTN             ExTokenNumber,
+  IN  PCD_PPI_CALLBACK  CallBackFunction
+  )
+{
+  if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (CallBackFunction == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return PeiRegisterCallBackWorker (ExTokenNumber, Guid, CallBackFunction, FALSE);
+}
+
+/**
+  Retrieves the next valid token number in a given namespace.
+
+  This is useful since the PCD infrastructure contains a sparse list of token numbers,
+  and one cannot a priori know what token numbers are valid in the database.
+
+  If TokenNumber is 0 and Guid is not NULL, then the first token from the token space specified by Guid is returned.
+  If TokenNumber is not 0 and Guid is not NULL, then the next token in the token space specified by Guid is returned.
+  If TokenNumber is 0 and Guid is NULL, then the first token in the default token space is returned.
+  If TokenNumber is not 0 and Guid is NULL, then the next token in the default token space is returned.
+  The token numbers in the default token space may not be related to token numbers in token spaces that are named by Guid.
+  If the next token number can be retrieved, then it is returned in TokenNumber, and EFI_SUCCESS is returned.
+  If TokenNumber represents the last token number in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+  If TokenNumber is not present in the token space specified by Guid, then EFI_NOT_FOUND is returned.
+
+
+  @param[in]       Guid        The 128-bit unique value that designates the namespace from which to extract the value.
+                               This is an optional parameter that may be NULL.  If this parameter is NULL, then a request
+                               is being made to retrieve tokens from the default token space.
+  @param[in, out]  TokenNumber A pointer to the PCD token number to use to find the subsequent token number.
+
+  @retval EFI_SUCCESS   The PCD service has retrieved the next valid token number.
+  @retval EFI_NOT_FOUND The PCD service could not find data from the requested token number.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdGetNextToken (
+  IN CONST EFI_GUID  *Guid  OPTIONAL,
+  IN OUT  UINTN      *TokenNumber
+  )
+{
+  UINTN              GuidTableIdx;
+  PEI_PCD_DATABASE   *PeiPcdDb;
+  EFI_GUID           *MatchGuid;
+  EFI_GUID           *GuidTable;
+  DYNAMICEX_MAPPING  *ExMapTable;
+  UINTN              Index;
+  BOOLEAN            Found;
+  BOOLEAN            PeiExMapTableEmpty;
+  UINTN              PeiNexTokenNumber;
+
+  if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  PeiPcdDb          = GetPcdDatabase ();
+  PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;
+  GuidTable         = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);
+
+  if (PeiPcdDb->ExTokenCount == 0) {
+    PeiExMapTableEmpty = TRUE;
+  } else {
+    PeiExMapTableEmpty = FALSE;
+  }
+
+  if (Guid == NULL) {
+    if (*TokenNumber > PeiNexTokenNumber) {
+      return EFI_NOT_FOUND;
+    }
+
+    (*TokenNumber)++;
+    if (*TokenNumber > PeiNexTokenNumber) {
+      *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+      return EFI_NOT_FOUND;
+    }
+
+    return EFI_SUCCESS;
+  } else {
+    if (PeiExMapTableEmpty) {
+      return EFI_NOT_FOUND;
+    }
+
+    MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof (EFI_GUID), Guid);
+
+    if (MatchGuid == NULL) {
+      return EFI_NOT_FOUND;
+    }
+
+    GuidTableIdx = MatchGuid - GuidTable;
+
+    ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);
+
+    Found = FALSE;
+    //
+    // Locate the GUID in ExMapTable first.
+    //
+    for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {
+      if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+        Found = TRUE;
+        break;
+      }
+    }
+
+    if (Found) {
+      //
+      // If given token number is PCD_INVALID_TOKEN_NUMBER, then return the first
+      // token number in found token space.
+      //
+      if (*TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
+        *TokenNumber = ExMapTable[Index].ExTokenNumber;
+        return EFI_SUCCESS;
+      }
+
+      for ( ; Index < PeiPcdDb->ExTokenCount; Index++) {
+        if ((ExMapTable[Index].ExTokenNumber == *TokenNumber) && (ExMapTable[Index].ExGuidIndex == GuidTableIdx)) {
+          break;
+        }
+      }
+
+      while (Index < PeiPcdDb->ExTokenCount) {
+        Index++;
+        if (Index == PeiPcdDb->ExTokenCount) {
+          //
+          // Exceed the length of ExMap Table
+          //
+          *TokenNumber = PCD_INVALID_TOKEN_NUMBER;
+          return EFI_NOT_FOUND;
+        } else if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+          //
+          // Found the next match
+          //
+          *TokenNumber = ExMapTable[Index].ExTokenNumber;
+          return EFI_SUCCESS;
+        }
+      }
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Retrieves the next valid PCD token namespace for a given namespace.
+
+  Gets the next valid token namespace for a given namespace. This is useful to traverse the valid
+  token namespaces on a platform.
+
+  @param[in, out]   Guid    An indirect pointer to EFI_GUID. On input it designates a known token
+                            namespace from which the search will start. On output, it designates the next valid
+                            token namespace on the platform. If *Guid is NULL, then the GUID of the first token
+                            space of the current platform is returned. If the search cannot locate the next valid
+                            token namespace, an error is returned and the value of *Guid is undefined.
+
+  @retval  EFI_SUCCESS      The PCD service retrieved the value requested.
+  @retval  EFI_NOT_FOUND    The PCD service could not find the next valid token namespace.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiPcdGetNextTokenSpace (
+  IN OUT CONST EFI_GUID  **Guid
+  )
+{
+  UINTN              GuidTableIdx;
+  EFI_GUID           *MatchGuid;
+  PEI_PCD_DATABASE   *PeiPcdDb;
+  DYNAMICEX_MAPPING  *ExMapTable;
+  UINTN              Index;
+  UINTN              Index2;
+  BOOLEAN            Found;
+  BOOLEAN            PeiExMapTableEmpty;
+  EFI_GUID           *GuidTable;
+
+  if (!FeaturePcdGet (PcdPeiFullPcdDatabaseEnable)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  ASSERT (Guid != NULL);
+
+  PeiPcdDb = GetPcdDatabase ();
+
+  if (PeiPcdDb->ExTokenCount == 0) {
+    PeiExMapTableEmpty = TRUE;
+  } else {
+    PeiExMapTableEmpty = FALSE;
+  }
+
+  if (PeiExMapTableEmpty) {
+    return EFI_NOT_FOUND;
+  }
+
+  ExMapTable = (DYNAMICEX_MAPPING *)((UINT8 *)PeiPcdDb + PeiPcdDb->ExMapTableOffset);
+  GuidTable  = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset);
+
+  if (*Guid == NULL) {
+    //
+    // return the first Token Space Guid.
+    //
+    *Guid = GuidTable + ExMapTable[0].ExGuidIndex;
+    return EFI_SUCCESS;
+  }
+
+  MatchGuid = ScanGuid (GuidTable, PeiPcdDb->GuidTableCount * sizeof (GuidTable[0]), *Guid);
+
+  if (MatchGuid == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  GuidTableIdx = MatchGuid - GuidTable;
+
+  Found = FALSE;
+  for (Index = 0; Index < PeiPcdDb->ExTokenCount; Index++) {
+    if (ExMapTable[Index].ExGuidIndex == GuidTableIdx) {
+      Found = TRUE;
+      break;
+    }
+  }
+
+  if (Found) {
+    Index++;
+    for ( ; Index < PeiPcdDb->ExTokenCount; Index++ ) {
+      if (ExMapTable[Index].ExGuidIndex != GuidTableIdx) {
+        Found = FALSE;
+        for (Index2 = 0; Index2 < Index; Index2++) {
+          if (ExMapTable[Index2].ExGuidIndex == ExMapTable[Index].ExGuidIndex) {
+            //
+            // This token namespace should have been found and output at preceding getting.
+            //
+            Found = TRUE;
+            break;
+          }
+        }
+
+        if (!Found) {
+          *Guid = (EFI_GUID *)((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset) + ExMapTable[Index].ExGuidIndex;
+          return EFI_SUCCESS;
+        }
+      }
+    }
+
+    *Guid = NULL;
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Get PCD value's size for POINTER type PCD.
+
+  The POINTER type PCD's value will be stored into a buffer in specified size.
+  The max size of this PCD's value is described in PCD's definition in DEC file.
+
+  @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table
+  @param MaxSize                  Maximum size of PCD's value
+  @param Database                 Pcd database in PEI phase.
+
+  @return PCD value's size for POINTER type PCD.
+
+**/
+UINTN
+GetPtrTypeSize (
+  IN    UINTN             LocalTokenNumberTableIdx,
+  OUT   UINTN             *MaxSize,
+  IN    PEI_PCD_DATABASE  *Database
+  )
+{
+  INTN       SizeTableIdx;
+  UINTN      LocalTokenNumber;
+  SIZE_INFO  *SizeTable;
+
+  SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
+
+  LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);
+
+  ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
+
+  SizeTable = (SIZE_INFO *)((UINT8 *)Database + Database->SizeTableOffset);
+
+  *MaxSize = SizeTable[SizeTableIdx];
+  //
+  // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
+  // PCD entry.
+  //
+  if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
+    //
+    // We have only two entry for VPD enabled PCD entry:
+    // 1) MAX Size.
+    // 2) Current Size
+    // We consider current size is equal to MAX size.
+    //
+    return *MaxSize;
+  } else {
+    //
+    // We have only two entry for Non-Sku enabled PCD entry:
+    // 1) MAX SIZE
+    // 2) Current Size
+    //
+    return SizeTable[SizeTableIdx + 1];
+  }
+}
+
+/**
+  Set PCD value's size for POINTER type PCD.
+
+  The POINTER type PCD's value will be stored into a buffer in specified size.
+  The max size of this PCD's value is described in PCD's definition in DEC file.
+
+  @param LocalTokenNumberTableIdx Index of PCD token number in PCD token table
+  @param CurrentSize              Maximum size of PCD's value
+  @param Database                 Pcd database in PEI phase.
+
+  @retval TRUE  Success to set PCD's value size, which is not exceed maximum size
+  @retval FALSE Fail to set PCD's value size, which maybe exceed maximum size
+
+**/
+BOOLEAN
+SetPtrTypeSize (
+  IN          UINTN             LocalTokenNumberTableIdx,
+  IN    OUT   UINTN             *CurrentSize,
+  IN          PEI_PCD_DATABASE  *Database
+  )
+{
+  INTN       SizeTableIdx;
+  UINTN      LocalTokenNumber;
+  SIZE_INFO  *SizeTable;
+  UINTN      MaxSize;
+
+  SizeTableIdx = GetSizeTableIndex (LocalTokenNumberTableIdx, Database);
+
+  LocalTokenNumber = *((UINT32 *)((UINT8 *)Database + Database->LocalTokenNumberTableOffset) + LocalTokenNumberTableIdx);
+
+  ASSERT ((LocalTokenNumber & PCD_DATUM_TYPE_ALL_SET) == PCD_DATUM_TYPE_POINTER);
+
+  SizeTable = (SIZE_INFO *)((UINT8 *)Database + Database->SizeTableOffset);
+
+  MaxSize = SizeTable[SizeTableIdx];
+  //
+  // SizeTable only contain record for PCD_DATUM_TYPE_POINTER type
+  // PCD entry.
+  //
+  if ((LocalTokenNumber & PCD_TYPE_VPD) != 0) {
+    //
+    // We shouldn't come here as we don't support SET for VPD
+    //
+    ASSERT (FALSE);
+    return FALSE;
+  } else {
+    if ((*CurrentSize > MaxSize) ||
+        (*CurrentSize == MAX_ADDRESS))
+    {
+      *CurrentSize = MaxSize;
+      return FALSE;
+    }
+
+    //
+    // We have only two entry for Non-Sku enabled PCD entry:
+    // 1) MAX SIZE
+    // 2) Current Size
+    //
+    SizeTable[SizeTableIdx + 1] = (SIZE_INFO)*CurrentSize;
+    return TRUE;
+  }
+}
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf
new file mode 100644
index 0000000000..61c53bdf70
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf
@@ -0,0 +1,361 @@
+## @file
+# PCD PEIM produces PCD database to manage all dynamic PCD in PEI phase and install Pcd Ppi service.
+#
+# This version PCD PEIM depends on the external PCD database binary file, not built in PCD data base.
+# There are two PCD PPIs as follows:
+#   1) PCD_PPI
+#      It is EDKII implementation which support Dynamic/DynamicEx Pcds.
+#   2) EFI_PEI_PCD_PPI
+#      It is defined by PI specification 1.2, Vol 3 which only support dynamicEx
+#      type Pcd.
+# For dynamicEx type PCD, it is compatible between PCD_PPI and EFI_PEI_PCD_PPI.
+# PCD PEIM driver will produce above two PPIs at same time.
+#
+# PCD database is generated as the separate binary image at build time. The binary image
+# will be intergrated into Firmware volume together with PCD driver.
+#
+# ////////////////////////////////////////////////////////////////////////////////
+# //                                                                            //
+# //                      Introduction of PCD database                          //
+# //                                                                            //
+# ////////////////////////////////////////////////////////////////////////////////
+#
+# 1, Introduction
+#    PCD database hold all dynamic type PCD information. The structure of PEI PCD
+#    database is generated by build tools according to dynamic PCD usage for
+#    specified platform.
+#
+# 2, Dynamic Type PCD
+#    Dynamic type PCD is used for the configuration/setting which value is determined
+#    dynamic. In contrast, the value of static type PCD (FeatureFlag, FixedPcd,
+#    PatchablePcd) is fixed in final generated FD image in build time.
+#
+#    2.1 The "dynamic" determination means one of below cases:
+#      a) The PCD setting value is produced by someone driver and consumed by
+#         other driver in execution time.
+#      b) The PCD setting value is set/get by user from FrontPage.
+#      c) The PCD setting value is produced by platform OEM vendor in specified area.
+#
+#    2.2 According to module distribution way, dynamic PCD could be classfied as:
+#      a) Dynamic:
+#         If module is released in source code and will be built with platform
+#         DSC, the dynamic PCD used by this module can be accessed as:
+#                 PcdGetxx(PcdSampleDynamicPcd);
+#         In building platform, build tools will translate PcdSampleDynamicPcd to
+#         pair of {Token Space Guid: Token Number} for this PCD.
+#      b) DynamicEx:
+#         If module is release as binary and will not pariticpate platform building,
+#         the dynamic PCD used by this module need be accessed as:
+#               PcdGetxxEx(gEfiMyTokenspaceGuid, PcdSampleDynamicPcd)
+#         Developer need explicity gives {Token Space Guid:Token Number} as parameter
+#         in writting source code.
+#
+#    2.3 According to PCD value's storage method, dynamic PCD could be classfied as:
+#      a) Default Storage:
+#         - The PCD value is stored in PCD database maintained by PCD driver in boot
+#           time memory.
+#         - This type is used for communication between PEIM/DXE driver, DXE/DXE
+#           driver. But all set/get value will be losted after boot-time memory
+#           is turn off.
+#         - [PcdsDynamicDefault] is used as section name for this type PCD in
+#           platform DSC file. [PcdsDynamicExDefault] is used for dynamicEx type PCD.
+#
+#      b) Variable Storage:
+#         - The PCD value is stored in variable area.
+#         - As default storage type, this type PCD could be used for PEI/DXE driver
+#           communication. But beside it, this type PCD could also be used to store
+#           the value associate with a HII setting via variable interface.
+#         - In PEI phase, the PCD value could only be got but can not be set due
+#           to variable area is readonly.
+#         - [PcdsDynamicHii] is used as section name for this type PCD in platform
+#           DSC file. [PcdsDynamicExHii] is for dynamicEx type PCD.
+#
+#      c) OEM specificed storage area:
+#         - The PCD value is stored in OEM specified area which base address is
+#           specified by PCD setting - PcdVpdBaseAddress64 or PcdVpdBaseAddress.
+#         - The area is read only for PEI and DXE phase.
+#         - [PcdsDynamicVpd] is used as section name for this type PCD in platform
+#           DSC file. [PcdsDynamicExVpd] is for dynamicex type PCD.
+#
+#    2.4 When and how to use dynamic PCD
+#      Module developer do not care the used PCD is dynamic or static when writting
+#      source code/INF. Dynamic PCD and dynamic type is pointed by platform integrator
+#      in platform DSC file. Please ref section 2.3 to get matching between dynamic
+#      PCD type and section name in DSC file.
+#
+# 3, PCD database:
+#    Although dynamic PCD could be in different storage type as above description,
+#    but the basic information and default value for all dynamic PCD is hold
+#    by PCD database maintained by PEI/DXE driver.
+#
+#    As the whole EFI BIOS boot path is divided into PEI/DXE phase, the PCD database
+#    also is divided into Pei/Dxe database maintaied by PcdPeim/PcdDxe driver separatly.
+#    To make PcdPeim's driver image smaller, PEI PCD database only hold all dynamic
+#    PCD information used in PEI phase or use in both PEI/DXE phase. And DXE PCD
+#    database contains all PCDs used in PEI/DXE phase in memory.
+#
+#    Build tool will generate PCD database into the separate binary file for
+#    PEI/DXE PCD driver according to dynamic PCD section in platform DSC file.
+#
+#    3.1 PcdPeim and PcdDxe
+#      PEI PCD database is maintained by PcdPeim driver run from flash. PcdPeim driver
+#      build guid hob in temporary memory and copy the binary data base from flash
+#      to temporary memory for PEI PCD database.
+#      DXE PCD database is maintained by PcdDxe driver.At entry point of PcdDxe driver,
+#      a new PCD database is allocated in boot-time memory which including all
+#      PEI PCD and DXE PCD entry.
+#
+#      Pcd driver should run as early as possible before any other driver access
+#      dynamic PCD's value. PEI/DXE "Apriori File" mechanism make it possible by
+#      making PcdPeim/PcdDxe as first dispatching driver in PEI/DXE phase.
+#
+#    3.2 Token space Guid/Token number, Platform token, Local token number
+#           Dynamic PCD
+#          +-----------+               +---------+
+#          |TokenSpace |               |Platform |
+#          |   Guid    |  build tool   | Token   |
+#          |    +      +-------------->| Number  |
+#          |  Token    |               +---------+`._
+#          |  Number   |                             `.
+#          +-----------+                               `.  +------+
+#                                                        `-|Local |
+#                                                          |Token |
+#                               DynamicEx PCD            ,-|Number|
+#                               +-----------+         ,-'  +------+
+#                               |TokenSpace |      ,-'
+#                               |   Guid    |  _,-'
+#                               |    +      +.'
+#                               |  Token    |
+#                               |  Number   |
+#                               +-----------+
+#
+#
+#      3.2.1 Pair of Token space guid + Token number
+#        Any type PCD is identified by pair of "TokenSpaceGuid + TokeNumber". But it
+#        is not easy maintained by PCD driver, and hashed token number will make
+#        searching slowly.
+#
+#      3.2.2 Platform Token Number
+#        "Platform token number" concept is introduced for mapping to a pair of
+#        "TokenSpaceGuid + TokenNumber". The platform token number is generated by
+#        build tool in autogen.h and all of them are continual in a platform scope
+#        started from 1.(0 meaning invalid internal token number)
+#        With auto-generated "platform token number", PcdGet(PcdSampleDynamicPcd)
+#        in source code is translated to LibPcdGet(_PCD_TOKEN_PcdSampleDynamicPcd)
+#        in autogen.h.
+#        Notes: The mapping between pair of "tokenspace guid + token number" and
+#        "internal token number" need build tool establish, so "platform token number"
+#        mechanism is not suitable for binary module which use DynamicEx type PCD.
+#        To access a dynamicEx type PCD, pair of "token space guid/token number" all need
+#        to be specificed for PcdSet/PcdGet accessing macro.
+#
+#        Platform Token Number is started from 1, and inceased continuous. From whole
+#        platform scope, there are two zones: PEI Zone and DXE Zone
+#                  |                      Platform Token Number
+#        ----------|----------------------------------------------------------------
+#        PEI Zone: |            1                 ~  PEI_LOCAL_TOKEN_NUMBER
+#        DXE Zone: | (PEI_LOCAL_TOKEN_NUMBER + 1) ~ (PEI_LOCAL_TOKEN_NUMBER + DXE_LOCAL_TOKEN_NUMBER)
+#
+#      3.2.3 Local Token Number
+#        To fast searching a PCD entry in PCD database, PCD driver translate
+#        platform token number to local token number via a mapping table.
+#        For binary DynamicEx type PCD, there is a another mapping table to translate
+#        "token space guid + token number" to local token number directly.
+#        Local token number is identifier for all internal interface in PCD PEI/DXE
+#        driver.
+#
+#        A local token number is a 32-bit value in following meaning:
+#         32 ------------- 28 ---------- 24 -------- 0
+#          | PCD type mask  | Datum Type  |  Offset  |
+#          +-----------------------------------------+
+#        where:
+#          PCd type mask: indicate Pcd type from following macro:
+#                         PCD_TYPE_DATA
+#                         PCD_TYPE_HII
+#                         PCD_TYPE_VPD
+#                         PCD_TYPE_STRING
+#          Datum Type   : indicate PCD vaue type from following macro:
+#                         PCD_DATUM_TYPE_POINTER
+#                         PCD_DATUM_TYPE_UINT8
+#                         PCD_DATUM_TYPE_UINT16
+#                         PCD_DATUM_TYPE_UINT32
+#                         PCD_DATUM_TYPE_UINT64
+#          Offset      : indicate the related offset of PCD value in PCD database array.
+#       Based on local token number, PCD driver could fast determine PCD type, value
+#       type and get PCD entry from PCD database.
+#
+#    3.3 PCD Database binary file
+#      PCD Database binary file will be created at build time as the standalone binary image.
+#      To understand the binary image layout, PCD Database C structure is still generated
+#      as comments by build tools in PCD driver's autogen.h/
+#      autogen.c file. In generated C structure, following information is stored:
+#      - ExMapTable: This table is used translate a binary dynamicex type PCD's
+#                    "tokenguid + token" to local token number.
+#      - LocalTokenNumberTable:
+#                    This table stores all local token number in array, use "Internal
+#                    token number" as array index to get PCD entry's offset fastly.
+#      - SizeTable:  This table stores the size information for all PCD entry.
+#      - GuidTable:  This table stores guid value for DynamicEx's token space,
+#                    HII type PCD's variable GUID.
+#      - SkuIdTable: TBD
+#      - SystemSkuId: TBD
+#      - PCD value structure:
+#                    Every PCD has a value record in PCD database. For different
+#                    datum type PCD has different record structure which will be
+#                    introduced in 3.3.1
+#
+#      In a PCD database structure, there are two major area: Init and UnInit.
+#      Init area is use stored above PCD internal structure such as ExMapTable,
+#      LocalTokenNumberTable etc and the (default) value of PCD which has default
+#      value specified in platform DSC file.
+#      Unint area is used stored the value of PCD which has no default value in
+#      platform DSC file, the value of NULL, 0 specified in platform DSC file can
+#      be seemed as "no default value".
+#
+#      3.3.1 Simple Sample PCD Database C Structure
+#        A general sample of PCD database structue is as follows:
+#        typedef struct _PCD_DATABASE {
+#          typedef struct _PCD_DATABASE_INIT {
+#            //===== Following is PCD database internal maintain structures
+#            DYNAMICEX_MAPPING ExMapTable[PEI_EXMAPPING_TABLE_SIZE];
+#            UINT32            LocalTokenNumberTable[PEI_LOCAL_TOKEN_NUMBER_TABLE_SIZE];
+#            GUID              GuidTable[PEI_GUID_TABLE_SIZE];
+#            SIZE_INFO         SizeTable[PEI_SIZE_TABLE_SIZE];
+#            UINT8             SkuIdTable[PEI_SKUID_TABLE_SIZE];
+#            SKU_ID            SystemSkuId;
+#
+#            //===== Following is value structure for PCD with default value
+#            ....
+#            ....
+#            ....
+#          } Init;
+#          typedef struct _PCD_DATABSE_UNINIT {
+#            //==== Following is value structure for PCD without default value
+#            ....
+#            ....
+#          } UnInit;
+#        }
+#
+#      3.3.2 PCD value structure in PCD database C structure
+#        The value's structure is generated by build tool in PCD database C structure.
+#        The PCDs in different datum type has different value structure.
+#
+#        3.3.2.1 UINT8/UINT16/UINT32/UINT64 datum type PCD
+#          The C structure for these datum type PCD is just a UINT8/UINT16/UINT32/UINT64
+#          data member in PCD database, For example:
+#          UINT16  PcdHardwareErrorRecordLevel_d3705011_bc19_4af7_be16_f68030378c15_VariableDefault_0;
+#          Above structure is generated by build tool, the member name is "PcdCName_Guidvalue"
+#          Member type is UINT16 according to PcdHardwareErrorRecordLevel declaration
+#          in DEC file.
+#
+#        3.3.2.2 VOID* datum type PCD
+#          The value of VOID* datum type PCD is a UINT8/UINT16 array in PCD database.
+#
+#          3.3.2.2.1 VOID* - string type
+#            If the default value for VOID* datum type PCD like L"xxx", the PCD is
+#            used for unicode string, and C structure of this datum type PCD is
+#            UINT16 string array in PCD database, for example:
+#            UINT16 StringTable[29];
+#            The number of 29 in above sample is max size of a unicode string.
+#
+#            If the default value for VOID* datum type PCD like "xxx", the PCD is
+#            used for ascii string, and C structure of this datum type PCD is
+#            UINT8 string array in PCD database, for example:
+#            UINT8 StringTable[20];
+#            The number of 20 in above sample is max size of a ascii string.
+#
+#          3.3.2.2.2 VOID* - byte array
+#            If the default value of VOID* datum type PCD like {'0x29', '0x01', '0xf2'}
+#            the PCD is used for byte array. The generated structrue is same as
+#            above ascii string table,
+#            UINT8 StringTable[13];
+#            The number of 13 in above sample is max size of byte array.
+#
+#      3.3.3 Some utility structures in PCD Database
+#        3.3.3.1 GuidTable
+#          GuidTable array is used to store all related GUID value in PCD database:
+#            - Variable GUID for HII type PCD
+#            - Token space GUID for dynamicex type PCD
+#
+#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PcdPeim
+  MODULE_UNI_FILE                = PcdPeim.uni
+  FILE_GUID                      = 9B3ADA4F-AE56-4c24-8DEA-F03B7558AE50
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 4.0
+  PCD_IS_DRIVER                  = PEI_PCD_DRIVER
+  ENTRY_POINT                    = PcdPeimInit
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC (EBC is for build only)
+#
+
+[Sources]
+  Service.c
+  Service.h
+  Pcd.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ChachaniBoardPkg/Project.dec
+  Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  PcdLib
+  PeiServicesLib
+  HobLib
+  BaseLib
+  PeimEntryPoint
+  DebugLib
+  MemoryAllocationLib
+
+[Guids]
+  ## PRODUCES            ## HOB
+  ## SOMETIMES_CONSUMES  ## HOB
+  gPcdDataBaseHobGuid
+  gPcdDataBaseSignatureGuid                     ## CONSUMES  ## GUID  # PCD database signature GUID.
+  gEfiMdeModulePkgTokenSpaceGuid                ## SOMETIMES_CONSUMES  ## GUID
+  gEfiAmdAgesaModulePkgTokenSpaceGuid
+  gEfiAmdAgesaPkgTokenSpaceGuid
+  gAmdCpmPkgTokenSpaceGuid
+  gAmdFspPkgGuid
+
+[Ppis]
+  gEfiPeiReadOnlyVariable2PpiGuid               ## SOMETIMES_CONSUMES
+  gPcdPpiGuid                                   ## PRODUCES
+  gEfiPeiPcdPpiGuid                             ## PRODUCES
+  gGetPcdInfoPpiGuid                            ## SOMETIMES_PRODUCES
+  gEfiGetPcdInfoPpiGuid                         ## SOMETIMES_PRODUCES
+  gEfiEndOfPeiSignalPpiGuid                     ## NOTIFY
+  gFspEfiPeiPcdPpiGuid                          ## SOMETIMES_PRODUCES
+  gFspEfiGetPcdInfoPpiGuid                      ## SOMETIMES_PRODUCES
+
+[FeaturePcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiFullPcdDatabaseEnable  ## CONSUMES
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress64 ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPcdCallBackNumberPerPcdEntry ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetNvStoreDefaultId       ## CONSUMES
+  gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection
+
+[Depex]
+  TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  PcdPeimExtra.uni
diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Intel/SmramSaveStateMap.h b/Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Intel/SmramSaveStateMap.h
new file mode 100644
index 0000000000..f83062e39c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Intel/SmramSaveStateMap.h
@@ -0,0 +1,324 @@
+/** @file
+SMRAM Save State Map Definitions.
+
+SMRAM Save State Map definitions based on contents of the
+Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+  Volume 3C, Section 34.4 SMRAM
+  Volume 3C, Section 34.5 SMI Handler Execution Environment
+  Volume 3C, Section 34.7 Managing Synchronous and Asynchronous SMIs
+
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef INTEL_SMRAM_SAVE_STATE_MAP_H_
+#define INTEL_SMRAM_SAVE_STATE_MAP_H_
+#define AMD_CPU  1
+///
+/// Default SMBASE address
+///
+#define SMM_DEFAULT_SMBASE  0x30000
+
+///
+/// Offset of SMM handler from SMBASE
+///
+#define SMM_HANDLER_OFFSET  0x8000
+
+///
+/// Offset of SMRAM Save State Map from SMBASE
+///
+#if AMD_CPU
+#define SMRAM_SAVE_STATE_MAP_OFFSET  0xfe00
+#else
+#define SMRAM_SAVE_STATE_MAP_OFFSET  0xfc00
+#endif
+
+#pragma pack (1)
+
+#if AMD_CPU
+///
+/// CPU save-state strcuture for AMD64 Architecture
+///
+typedef struct {
+  UINT8     Reserved[0xF8];  // FE00h - FEF7h , Reserved, 248 Bytes, --
+  UINT32    SMBASE;          // FEF8h, SMBASE, Doubleword, Read/Write
+  UINT32    SMMRevId;        // FEFCh, SMM-Revision identifier, Doubleword, Read-Only
+  UINT16    IORestart;       // FF00h, I/O Instruction Restart, Word, Read/Write
+  UINT16    AutoHALTRestart; // FF02h, Auti-Halt Restart, Word, Read/Write
+  UINT8     Reserved1[0x84]; // FF04h - FF87h, Reserved, 132 Bytes --
+  UINT32    GdtBase;         // FF88h, GDT Base, Doubleword, Read-Only
+  UINT64    Reserved2;       // FF8Ch - FF93h, Quadword, --
+  UINT32    IDTBase;         // FF94h, IDT Base, Doubleword, Read-Only
+  UINT8     Reserved3[0x10]; // FF98 - FFA7h, Reserved, 16Bytes, --
+  UINT32    _ES;             // FFA8h, ES, Doubleword, Read-Only
+  UINT32    _CS;             // FFACh, CS, Doubleword, Read-Only
+  UINT32    _SS;             // FFB0h, SS, Doubleword, Read-Only
+  UINT32    _DS;             // FFB4h, DS, Doubleword, Read-Only
+  UINT32    _FS;             // FFB8h, FS, Doubleword, Read-Only
+  UINT32    _GS;             // FFBCh, GS, Doubleword, Read-Only
+  UINT32    LDTBase;         // FFC0h, LDT Base, Doubleword, Read-Only
+  UINT32    _TR;             // FFC4h, TR, Doubleword, Read-Only
+  UINT32    _DR7;            // FFC8h, DR7, Doubleword, Read-Only
+  UINT32    _DR6;            // FFCCh, DR6, Doubleword, Read-Only
+  UINT32    _EAX;            // FFD0h, EAX, Doubleword, Read/Write
+  UINT32    _ECX;            // FFD4h, ECX, Doubleword, Read/Write
+  UINT32    _EDX;            // FFD8h, EDX, Doubleword, Read/Write
+  UINT32    _EBX;            // FFDCh, EBX, Doubleword, Read/Write
+  UINT32    _ESP;            // FFE0h, ESP, Doubleword, Read/Write
+  UINT32    _EBP;            // FFE4h, EBP, Doubleword, Read/Write
+  UINT32    _ESI;            // FFE8h, ESI, Doubleword, Read/Write
+  UINT32    _EDI;            // FFECh, EDI, Doubleword, Read/Write
+  UINT32    _EIP;            // FFF0h, EIP, Doubleword, Read/Write
+  UINT32    _EFLAGS;         // FFF4h, EFLAGS, Doubleword, Read/Write
+  UINT32    _CR3;            // FFF8h, CR3, Doubleword, Read/Write
+  UINT32    _CR0;            // FFFCh, CR0, Doubleword, Read/Write
+} SMRAM_SAVE_STATE_MAP32;
+
+typedef struct {
+  UINT16    _ES;                 // FE00h, ES Selector, Word, Read-Only
+  UINT16    ESAttributes;        // FE02h, ES Attributes, Word, Read-Only
+  UINT32    ESLimit;             // FE04h, ES Limit, Doubleword, Read-Only
+  UINT64    ESBase;              // FE08h, ES Base, Quadword, Read-Only
+  UINT16    _CS;                 // FE10h, CS Selector, Word, Read-Only
+  UINT16    CSAttributes;        // FE12h, CS Attributes, Word, Read-Only
+  UINT32    CSLimit;             // FE14h, CS Limit, Doubleword, Read-Only
+  UINT64    CSBase;              // FE18h, CS Base, Quadword, Read-Only
+  UINT16    _SS;                 // FE20h, SS Selector, Word, Read-Only
+  UINT16    SSAttributes;        // FE22h, SS Attributes, Word, Read-Only
+  UINT32    SSLimit;             // FE24h, SS Limit, Doubleword, Read-Only
+  UINT64    SSBase;              // FE28h, SS Base, Quadword, Read-Only
+  UINT16    _DS;                 // FE30h, DS Selector, Word, Read-Only
+  UINT16    DSAttributes;        // FE32h, DS Attributes, Word, Read-Only
+  UINT32    DSLimit;             // FE34h, DS Limit, Doubleword, Read-Only
+  UINT64    DSBase;              // FE38h, DS Base, Quadword, Read-Only
+  UINT16    _FS;                 // FE40h, FS Selector, Word, Read-Only
+  UINT16    FSAttributes;        // FE42h, FS Attributes, Word, Read-Only
+  UINT32    FSLimit;             // FE44h, FS Limit, Doubleword, Read-Only
+  UINT64    FSBase;              // FE48h, FS Base, Quadword, Read-Only
+  UINT16    _GS;                 // FE50h, GS Selector, Word, Read-Only
+  UINT16    GSAttributes;        // FE52h, GS Attributes, Word, Read-Only
+  UINT32    GSLimit;             // FE54h, GS Limit, Doubleword, Read-Only
+  UINT64    GSBase;              // FE58h, GS Base, Quadword, Read-Only
+  UINT8     Reserved1[4];        // FE60h - FE63h, GDTR Reserved, 4 Bytes, Read-Only
+  UINT16    GdtrLimit;           // FE64h, GDTR Limit, Word, Read-Only
+  UINT8     Reserved2[2];        // FE66h - FE67h, Reserved, 2 Bytes, Read-Only
+  //  UINT64  GDTR_Base;            // FE68h, GDTR Base, Quadword, Read-Only
+  UINT32    GdtrBaseLoDword;
+  UINT32    GdtrBaseHiDword;
+  UINT16    LdtrSelector;        // FE70h, LDTR Selector, Word, Read-Only
+  UINT16    LdtrAttributes;      // FE72h, LDTR Attributes, Word, Read-Only
+  UINT32    LdtrLimit;           // FE74h, LDTR Limit, Doubleword, Read-Only
+  //  UINT64  LDTR_Base;            // FE78h, LDTR Base, Quadword, Read-Only
+  UINT32    LdtrBaseLoDword;
+  UINT32    LdtrBaseHiDword;
+  UINT8     Reserved3[4];        // FE80h - FE83h (PID: 24593 (PUB) 3.20 p.279 has a technical errors), IDTR Reserved, 4 Bytes, Read-Only
+  UINT16    IdtrLimit;           // FE84h, IDTR Limit, Word, Read-Only
+  UINT8     Reserved4[2];        // FE86h - FE87h (PID: 24593 (PUB) 3.20 p.279 has a technical errors), IDTR Reserved, 2 Bytes, Read-Only
+  //  UINT64  IDTR_Base;            // FE88h, IDTR Base, Quadword, Read-Only
+  UINT32    IdtrBaseLoDword;
+  UINT32    IdtrBaseHiDword;
+  UINT16    TrSelector;           // FE90h, TR Selector, Word, Read-Only
+  UINT16    TrAttributes;         // FE92h, TR Attributes, Word, Read-Only
+  UINT32    TrLimit;              // FE94h, TR Limit, Doubleword, Read-Only
+  UINT64    TrBase;               // FE98h, TR Base, Quadword, Read-Only
+  UINT64    IO_RESTART_RIP;       // FEA0h, I/O Instruction Restart RIP, Quadword, Read-Only
+  UINT64    IO_RESTART_RCX;       // FEA8h, I/O Instruction Restart RCX, Quadword, Read-Only
+  UINT64    IO_RESTART_RSI;       // FEB0h, I/O Instruction Restart RSI, Quadword, Read-Only
+  UINT64    IO_RESTART_RDI;       // FEB8h, I/O Instruction Restart RDI, Quadword, Read-Only
+  UINT32    SMM_IO_TRAP;          // FEC0h, I/O Instruction Restart Dword SMMFEC0 [SMM IO Trap Offset], Read-Only
+  UINT32    LocalSmiStatus;       // FEC4h, SMMFEC4 [Local SMI Status], Doubleword, Read-Only
+  UINT8     SMM_IO_RESTART;       // FEC8h, SMMFEC8 [SMM IO Restart Byte], Byte, Read/Write
+  UINT8     AutoHALTRestart;      // FEC9h, SMMFEC9 [Auto Halt Restart Offset], Byte, Read/Write
+  UINT8     NMI_MASK;             // FECAh, SMMFECA [NMI Mask], Byte, Read/Write
+  UINT8     Reserved5[5];         // FECBh - FECFh, Reserved, 5 Bytes, --
+  UINT64    EFER;                 // FED0h, EFER, Quadword, Read-Only
+  UINT64    SMM_SVM_State;        // FED8h, SMMFED8 [SMM SVM State], Read-Only
+  UINT64    Guest_VMCB_PHY_ADDR;  // FEE0h, Guest VMCB physical address, Read-Only
+  UINT64    SVM_Virtual_INT_CTRL; // FEE8h, SVM Virtual Interrupt Control, Read-Only
+  UINT8     Reserved6[12];        // FEF0h - FEFBh, Reserved, 12 Bytes (PID: 42300 Family 15h BKDG (NDA) 1.11 p.49 has a technial error), --
+  UINT32    SMMRevId;             // FEFCh, SMMFEFC [SMM-Revision-Indentifier], Doubleword, Read/Write
+  UINT32    SMBASE;               // FF00h, SMMFF00 [SMM Base Address (SMM_BASE)], Read/Write
+  UINT8     Reserved7[28];        // FF04h, Reserved, 24 Bytes, --
+  UINT64    GuestPAT;             // FF20h, Guest PAT, Quadword, Read-Only
+  UINT64    HostEFER;             // FF28h, Host EFER, Quadword, Read-Only
+  UINT64    HostCR4;              // FF30h, Host CR4, Quadword, Read-Only
+  UINT64    NestedCR3;            // FF38h, Nested CR3, Quadword, Read-Only
+  UINT64    HostCR0;              // FF40h, Host CR0, Quadword, Read-Only
+  UINT64    _CR4;                 // FF48h, CR4, Quadword, Read-Only
+  UINT64    _CR3;                 // FF50h, CR3, Quadword, Read-Only
+  UINT64    _CR0;                 // FF58h, CR0, Quadword, Read-Only
+  UINT64    _DR7;                 // FF60h, DR7, Quadword, Read-Only
+  UINT64    _DR6;                 // FF68h, DR6, Quadword, Read-Only
+  UINT64    _RFLAGS;              // FF70h, RFLAGS, Quadword, Read/Write
+  UINT64    _RIP;                 // FF78h, RIP, Quadword, Read/Write
+  UINT64    _R15;                 // FF80h, R15, Quadword, Read/Write
+  UINT64    _R14;                 // FF88h, R14, Quadword, Read/Write
+  UINT64    _R13;                 // FF90h, R13, Quadword, Read/Write
+  UINT64    _R12;                 // FF98h, R12, Quadword, Read/Write
+  UINT64    _R11;                 // FFA0h, R11, Quadword, Read/Write
+  UINT64    _R10;                 // FFA8h, R10, Quadword, Read/Write
+  UINT64    _R9;                  // FFB0h, R9, Quadword, Read/Write
+  UINT64    _R8;                  // FFB8, R8, Quadword, Read/Write
+  UINT64    _RDI;                 // FFC0h, RDI, Quadword, Read/Write
+  UINT64    _RSI;                 // FFD8h, RSI, Quadword, Read/Write
+  UINT64    _RBP;                 // FFD0h, RBP, Quadword, Read/Write
+  UINT64    _RSP;                 // FFE0h, RSP, Quadword, Read/Write
+  UINT64    _RBX;                 // FFE0h, RBX, Quadword, Read/Write
+  UINT64    _RDX;                 // FFE8h, RDX, Quadword, Read/Write
+  UINT64    _RCX;                 // FFF0h, RCX, Quadword, Read/Write
+  UINT64    _RAX;                 // FFF8h, RAX, Quadword, Read/Write
+} SMRAM_SAVE_STATE_MAP64;
+#else
+///
+/// 32-bit SMRAM Save State Map
+///
+typedef struct {
+  UINT8     Reserved[0x200]; // 7c00h
+                             // Padded an extra 0x200 bytes so 32-bit and 64-bit
+                             // SMRAM Save State Maps are the same size
+  UINT8     Reserved1[0xf8]; // 7e00h
+  UINT32    SMBASE;          // 7ef8h
+  UINT32    SMMRevId;        // 7efch
+  UINT16    IORestart;       // 7f00h
+  UINT16    AutoHALTRestart; // 7f02h
+  UINT8     Reserved2[0x9C]; // 7f08h
+  UINT32    IOMemAddr;       // 7fa0h
+  UINT32    IOMisc;          // 7fa4h
+  UINT32    _ES;             // 7fa8h
+  UINT32    _CS;             // 7fach
+  UINT32    _SS;             // 7fb0h
+  UINT32    _DS;             // 7fb4h
+  UINT32    _FS;             // 7fb8h
+  UINT32    _GS;             // 7fbch
+  UINT32    Reserved3;       // 7fc0h
+  UINT32    _TR;             // 7fc4h
+  UINT32    _DR7;            // 7fc8h
+  UINT32    _DR6;            // 7fcch
+  UINT32    _EAX;            // 7fd0h
+  UINT32    _ECX;            // 7fd4h
+  UINT32    _EDX;            // 7fd8h
+  UINT32    _EBX;            // 7fdch
+  UINT32    _ESP;            // 7fe0h
+  UINT32    _EBP;            // 7fe4h
+  UINT32    _ESI;            // 7fe8h
+  UINT32    _EDI;            // 7fech
+  UINT32    _EIP;            // 7ff0h
+  UINT32    _EFLAGS;         // 7ff4h
+  UINT32    _CR3;            // 7ff8h
+  UINT32    _CR0;            // 7ffch
+} SMRAM_SAVE_STATE_MAP32;
+
+///
+/// 64-bit SMRAM Save State Map
+///
+typedef struct {
+  UINT8     Reserved1[0x1d0]; // 7c00h
+  UINT32    GdtBaseHiDword;   // 7dd0h
+  UINT32    LdtBaseHiDword;   // 7dd4h
+  UINT32    IdtBaseHiDword;   // 7dd8h
+  UINT8     Reserved2[0xc];   // 7ddch
+  UINT64    IO_EIP;           // 7de8h
+  UINT8     Reserved3[0x50];  // 7df0h
+  UINT32    _CR4;             // 7e40h
+  UINT8     Reserved4[0x48];  // 7e44h
+  UINT32    GdtBaseLoDword;   // 7e8ch
+  UINT32    Reserved5;        // 7e90h
+  UINT32    IdtBaseLoDword;   // 7e94h
+  UINT32    Reserved6;        // 7e98h
+  UINT32    LdtBaseLoDword;   // 7e9ch
+  UINT8     Reserved7[0x38];  // 7ea0h
+  UINT64    EptVmxControl;    // 7ed8h
+  UINT32    EnEptVmxControl;  // 7ee0h
+  UINT8     Reserved8[0x14];  // 7ee4h
+  UINT32    SMBASE;           // 7ef8h
+  UINT32    SMMRevId;         // 7efch
+  UINT16    IORestart;        // 7f00h
+  UINT16    AutoHALTRestart;  // 7f02h
+  UINT8     Reserved9[0x18];  // 7f04h
+  UINT64    _R15;             // 7f1ch
+  UINT64    _R14;
+  UINT64    _R13;
+  UINT64    _R12;
+  UINT64    _R11;
+  UINT64    _R10;
+  UINT64    _R9;
+  UINT64    _R8;
+  UINT64    _RAX;            // 7f5ch
+  UINT64    _RCX;
+  UINT64    _RDX;
+  UINT64    _RBX;
+  UINT64    _RSP;
+  UINT64    _RBP;
+  UINT64    _RSI;
+  UINT64    _RDI;
+  UINT64    IOMemAddr;       // 7f9ch
+  UINT32    IOMisc;          // 7fa4h
+  UINT32    _ES;             // 7fa8h
+  UINT32    _CS;
+  UINT32    _SS;
+  UINT32    _DS;
+  UINT32    _FS;
+  UINT32    _GS;
+  UINT32    _LDTR;           // 7fc0h
+  UINT32    _TR;
+  UINT64    _DR7;            // 7fc8h
+  UINT64    _DR6;
+  UINT64    _RIP;            // 7fd8h
+  UINT64    IA32_EFER;       // 7fe0h
+  UINT64    _RFLAGS;         // 7fe8h
+  UINT64    _CR3;            // 7ff0h
+  UINT64    _CR0;            // 7ff8h
+} SMRAM_SAVE_STATE_MAP64;
+#endif
+
+///
+/// Union of 32-bit and 64-bit SMRAM Save State Maps
+///
+typedef union  {
+  SMRAM_SAVE_STATE_MAP32    x86;
+  SMRAM_SAVE_STATE_MAP64    x64;
+} SMRAM_SAVE_STATE_MAP;
+
+///
+/// Minimum SMM Revision ID that supports IOMisc field in SMRAM Save State Map
+///
+#define SMRAM_SAVE_STATE_MIN_REV_ID_IOMISC  0x30004
+
+///
+/// SMRAM Save State Map IOMisc I/O Length Values
+///
+#define  SMM_IO_LENGTH_BYTE   0x01
+#define  SMM_IO_LENGTH_WORD   0x02
+#define  SMM_IO_LENGTH_DWORD  0x04
+
+///
+/// SMRAM Save State Map IOMisc I/O Instruction Type Values
+///
+#define  SMM_IO_TYPE_IN_IMMEDIATE   0x9
+#define  SMM_IO_TYPE_IN_DX          0x1
+#define  SMM_IO_TYPE_OUT_IMMEDIATE  0x8
+#define  SMM_IO_TYPE_OUT_DX         0x0
+#define  SMM_IO_TYPE_INS            0x3
+#define  SMM_IO_TYPE_OUTS           0x2
+#define  SMM_IO_TYPE_REP_INS        0x7
+#define  SMM_IO_TYPE_REP_OUTS       0x6
+
+///
+/// SMRAM Save State Map IOMisc structure
+///
+typedef union {
+  struct {
+    UINT32    SmiFlag   : 1;
+    UINT32    Length    : 3;
+    UINT32    Type      : 4;
+    UINT32    Reserved1 : 8;
+    UINT32    Port      : 16;
+  } Bits;
+  UINT32    Uint32;
+} SMRAM_SAVE_STATE_IOMISC;
+
+#pragma pack ()
+
+#endif
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114605): https://edk2.groups.io/g/devel/message/114605
Mute This Topic: https://groups.io/mt/103975489/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (29 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 30/32] AMD/VanGoghBoard: Check in EDK2 override files Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:30 ` [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Chang, Abner via groups.io
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

From: Duke Zhai <Duke.Zhai@amd.com>

BZ #:4640
In V2: Improve coding style.
  1.Remove the leading underscore and use double underscore at trailing in C header files.
  2.Remove old tianocore licenses and redundant license description.
  3.Improve coding style. For example: remove space between @param.

In V1:
  Initial AMD SmmControlPei module in Silicon folder.
  This module initializes SMM-related registers, and installs gPeiSmmControlPpi.

Signed-off-by: Duke Zhai <duke.zhai@amd.com>
Cc: Eric Xing <eric.xing@amd.com>
Cc: Ken Yao <ken.yao@amd.com>
Cc: Igniculus Fu <igniculus.fu@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
---
 .../Smm/SmmControlPei/SmmControlPei.c         | 307 ++++++++++++++++++
 .../Smm/SmmControlPei/SmmControlPei.inf       |  40 +++
 2 files changed, 347 insertions(+)
 create mode 100644 Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.c
 create mode 100644 Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.inf

diff --git a/Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.c b/Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.c
new file mode 100644
index 0000000000..4752aede9c
--- /dev/null
+++ b/Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.c
@@ -0,0 +1,307 @@
+/** @file
+  Implements SmmControlPei.c
+
+  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/SmmControl.h>
+#include <Include/FchRegistersCommon.h>
+
+/**
+  This routine generates an SMI
+
+  @param[in]       PeiServices           Describes the list of possible PEI Services.
+  @param[in]       This                  The pointer to this instance of this PPI.
+  @param[in, out]  ArgumentBuffer        The buffer of argument
+  @param[in, out]  ArgumentBufferSize    The size of the argument buffer
+  @param[in]       Periodic              TRUE to indicate a periodical SMI
+  @param[in]       ActivationInterval    Interval of periodic SMI
+
+  @retval  EFI_SUCCESS            SMI generated.
+  @retval  EFI_INVALID_PARAMETER  Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+PeiTrigger (
+  IN     EFI_PEI_SERVICES     **PeiServices,
+  IN     PEI_SMM_CONTROL_PPI  *This,
+  IN OUT INT8                 *ArgumentBuffer OPTIONAL,
+  IN OUT UINTN                *ArgumentBufferSize OPTIONAL,
+  IN     BOOLEAN              Periodic OPTIONAL,
+  IN     UINTN                ActivationInterval OPTIONAL
+  );
+
+/**
+  Clear SMI related chipset status.
+
+  @param[in]  PeiServices           Describes the list of possible PEI Services.
+  @param[in]  This                  The pointer to this instance of this PPI.
+  @param[in]  Periodic              TRUE to indicate a periodical SMI.
+
+  @return  Return value from ClearSmi()
+**/
+EFI_STATUS
+EFIAPI
+PeiClear (
+  IN EFI_PEI_SERVICES     **PeiServices,
+  IN PEI_SMM_CONTROL_PPI  *This,
+  IN BOOLEAN              Periodic OPTIONAL
+  );
+
+STATIC PEI_SMM_CONTROL_PPI  mSmmControlPpi = {
+  PeiTrigger,
+  PeiClear
+};
+
+STATIC EFI_PEI_PPI_DESCRIPTOR  mPpiList = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gPeiSmmControlPpiGuid,
+  &mSmmControlPpi
+};
+
+/**
+ Init related registers
+
+ @param [in]        None
+
+ @retval  EFI_LOAD_ERROR  Get ACPI MMIO base error.
+ @retval  EFI_SUCCESS     The function completed successfully..
+*/
+EFI_STATUS
+SmmControlPeiPreInit (
+  VOID
+  )
+{
+  UINT16  SmmControlData16;
+  UINT16  SmmControlMask16;
+  UINT32  SmmControlData32;
+  UINT8   SmmControlIndex;
+  UINT16  AcpiPmBase;
+
+  //
+  // Get ACPI MMIO base and AcpiPm1EvtBlk address
+  //
+  AcpiPmBase = MmioRead16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG60);
+
+  if (0 == AcpiPmBase) {
+    return EFI_LOAD_ERROR;
+  }
+
+  //
+  // Clean up all SMI status and enable bits
+  //
+  // Clear all SmiControl registers
+  SmmControlData32 = 0;
+  for (SmmControlIndex = FCH_SMI_REGA0; SmmControlIndex <= FCH_SMI_REGC4; SmmControlIndex += 4) {
+    MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + SmmControlIndex, SmmControlData32);
+  }
+
+  // Clear all SmiStatus registers (SmiStatus0-4)
+  SmmControlData32 = 0xFFFFFFFF;
+  MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG80, SmmControlData32);
+  MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG84, SmmControlData32);
+  MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG88, SmmControlData32);
+  MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG8C, SmmControlData32);
+  MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG90, SmmControlData32);
+
+  //
+  // If SCI is not enabled, clean up all ACPI PM status/enable registers
+  //
+  SmmControlData16 = IoRead16 (AcpiPmBase + R_FCH_ACPI_PM_CONTROL);
+  if (!(SmmControlData16 & BIT0)) {
+    // Clear WAKE_EN, RTC_EN, SLPBTN_EN, GBL_EN and TMR_EN
+    SmmControlData16 = 0;
+    SmmControlMask16 = (UINT16) ~(BIT15 + BIT10 + BIT9 + BIT5 + BIT0);
+    IoAndThenOr16 (AcpiPmBase + R_FCH_ACPI_PM1_ENABLE, SmmControlMask16, SmmControlData16);
+
+    // Clear WAKE_STS, RTC_STS, SLPBTN_STS, GBL_STS and TMR_STS
+    SmmControlData16 = BIT15 + BIT10 + BIT9 + BIT5 + BIT0;
+    IoWrite16 (AcpiPmBase + R_FCH_ACPI_PM1_STATUS, SmmControlData16);
+  }
+
+  //
+  // Set the EOS Bit
+  // Clear SmiEnB to enable SMI function
+  //
+  SmmControlData32  = MmioRead32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG98);
+  SmmControlData32 |= BIT28;
+  SmmControlData32 &= ~BIT31;
+  MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG98, SmmControlData32);
+
+  //
+  // Enable CmdPort SMI
+  //
+  SmmControlData32  = MmioRead32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REGB0);
+  SmmControlData32 &= ~(BIT22 + BIT23);
+  SmmControlData32 |= BIT22;
+  MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REGB0, SmmControlData32);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Clear the SMI status
+
+
+  @retval EFI_SUCCESS             The function completes successfully
+**/
+EFI_STATUS
+ClearSmi (
+  VOID
+  )
+{
+  UINT32  SmmControlData32;
+
+  //
+  // Clear SmiCmdPort Status Bit
+  //
+  SmmControlData32 = BIT11;
+  MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG88, SmmControlData32);
+
+  //
+  // Set the EOS Bit if it is currently cleared so we can get an SMI otherwise
+  // leave the register alone
+  //
+  SmmControlData32 = MmioRead32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG98);
+  if ((SmmControlData32 & BIT28) == 0) {
+    SmmControlData32 |= BIT28;
+    MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REG98, SmmControlData32);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine generates an SMI
+
+  @param[in]       PeiServices           Describes the list of possible PEI Services.
+  @param[in]       This                  The pointer to this instance of this PPI.
+  @param[in, out]  ArgumentBuffer        The buffer of argument
+  @param[in, out]  ArgumentBufferSize    The size of the argument buffer
+  @param[in]       Periodic              TRUE to indicate a periodical SMI
+  @param[in]       ActivationInterval    Interval of periodic SMI
+
+  @retval  EFI_SUCCESS            SMI generated.
+  @retval  EFI_INVALID_PARAMETER  Some parameter value passed is not supported
+**/
+EFI_STATUS
+EFIAPI
+PeiTrigger (
+  IN     EFI_PEI_SERVICES     **PeiServices,
+  IN     PEI_SMM_CONTROL_PPI  *This,
+  IN OUT INT8                 *ArgumentBuffer OPTIONAL,
+  IN OUT UINTN                *ArgumentBufferSize OPTIONAL,
+  IN     BOOLEAN              Periodic OPTIONAL,
+  IN     UINTN                ActivationInterval OPTIONAL
+  )
+{
+  UINT8   bIndex;
+  UINT8   bData;
+  UINT32  SmmControlData32;
+  UINT16  SmiCmdPort;
+
+  if (Periodic) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (NULL == ArgumentBuffer) {
+    bIndex = 0xff;
+  } else {
+    bIndex = *ArgumentBuffer;
+  }
+
+  if (NULL == ArgumentBufferSize) {
+    bData = 0xff;
+  } else {
+    bData = (UINT8)*ArgumentBufferSize;
+  }
+
+  //
+  // Enable CmdPort SMI
+  //
+  SmmControlData32  = MmioRead32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REGB0);
+  SmmControlData32 &= ~(BIT22 + BIT23);
+  SmmControlData32 |= BIT22;
+  MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + FCH_SMI_REGB0, SmmControlData32);
+
+  SmiCmdPort = PcdGet16 (PcdAmdFchCfgSmiCmdPortAddr);
+
+  //
+  // Issue command port SMI
+  //
+  IoWrite16 (SmiCmdPort, (bData << 8) + bIndex);
+  return EFI_SUCCESS;
+}
+
+/**
+  Clear SMI related chipset status.
+
+  @param[in]  PeiServices           Describes the list of possible PEI Services.
+  @param[in]  This                  The pointer to this instance of this PPI.
+  @param[in]  Periodic              TRUE to indicate a periodical SMI.
+
+  @return  Return value from ClearSmi()
+**/
+EFI_STATUS
+EFIAPI
+PeiClear (
+  IN EFI_PEI_SERVICES     **PeiServices,
+  IN PEI_SMM_CONTROL_PPI  *This,
+  IN BOOLEAN              Periodic OPTIONAL
+  )
+{
+  if (Periodic) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return ClearSmi ();
+}
+
+/**
+  This is the constructor for the SMM Control Ppi.
+
+  This function installs PEI_SMM_CONTROL_PPI.
+
+  @param   FileHandle       Handle of the file being invoked.
+  @param   PeiServices      Describes the list of possible PEI Services.
+
+  @retval EFI_UNSUPPORTED There's no Intel ICH on this platform
+  @return The status returned from PeiServicesInstallPpi().
+
+--*/
+EFI_STATUS
+SmmControlPeiEntry (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS     Status;
+  EFI_BOOT_MODE  BootMode;
+
+  Status = PeiServicesGetBootMode (&BootMode);
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "PeiSmmControl Enter\n"));
+
+  if (BootMode != BOOT_ON_S3_RESUME) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Initialize EFI library
+  //
+  Status = SmmControlPeiPreInit ();
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PeiServicesInstallPpi (&mPpiList);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.inf b/Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.inf
new file mode 100644
index 0000000000..d6c984f02a
--- /dev/null
+++ b/Silicon/AMD/VanGoghBoard/Smm/SmmControlPei/SmmControlPei.inf
@@ -0,0 +1,40 @@
+## @file
+# AMD Smm Contro lPei
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PeiSmmControl
+  FILE_GUID                      = EC9519B1-E788-4C45-B695-244457442D64
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SmmControlPeiEntry
+
+[Sources.common]
+  SmmControlPei.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  AgesaPublic/AgesaPublic.dec
+
+[LibraryClasses]
+  IoLib
+  DebugLib
+  PeiServicesLib
+  PeimEntryPoint
+
+[Guids]
+
+[Pcd]
+  gEfiAmdAgesaPkgTokenSpaceGuid.PcdAmdFchCfgSmiCmdPortAddr      ## CONSUMES
+
+[Ppis]
+  gPeiSmmControlPpiGuid            #PRODUCED
+
+[Depex]
+  gEfiPeiMasterBootModePpiGuid
-- 
2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114606): https://edk2.groups.io/g/devel/message/114606
Mute This Topic: https://groups.io/mt/103975490/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [edk2-devel] [PATCH V3 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (30 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:11 ` Zhai, MingXin (Duke) via groups.io
  2024-01-26 13:30 ` [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Chang, Abner via groups.io
  32 siblings, 0 replies; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 13:11 UTC (permalink / raw)
  To: devel; +Cc: Eric Xing, Ken Yao, Igniculus Fu, Abner Chang

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="yes", Size: 366 bytes --]



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114608): https://edk2.groups.io/g/devel/message/114608
Mute This Topic: https://groups.io/mt/103975493/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code
  2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
                   ` (31 preceding siblings ...)
  2024-01-26 13:11 ` [edk2-devel] [PATCH V3 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 13:30 ` Chang, Abner via groups.io
  2024-01-29  3:23   ` Zhai, MingXin (Duke) via groups.io
  32 siblings, 1 reply; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-26 13:30 UTC (permalink / raw)
  To: Zhai, MingXin, devel

[-- Attachment #1: Type: text/plain, Size: 587 bytes --]

Hi Duke,
Next time please also CC reviewers in the cover letter, thus the cover letter can be also sent to reviewers directly.
For the entire patch set: Reviewed-by: Abner Chang <abner.chang@amd.com>

Thanks
Abner


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114611): https://edk2.groups.io/g/devel/message/114611
Mute This Topic: https://groups.io/mt/103975434/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 1029 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code
  2024-01-26 13:30 ` [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Chang, Abner via groups.io
@ 2024-01-29  3:23   ` Zhai, MingXin (Duke) via groups.io
  2024-01-29  4:46     ` Chang, Abner via groups.io
  0 siblings, 1 reply; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-29  3:23 UTC (permalink / raw)
  To: Chang, Abner, devel@edk2.groups.io

[-- Attachment #1: Type: text/plain, Size: 1131 bytes --]

[AMD Official Use Only - General]

Hi Abner,

Thanks your remind. I will CC reviewers next time.


Thanks!

From: Chang, Abner via Groups.Io <abner.chang=amd.com@groups.io>
Sent: Friday, January 26, 2024 9:30 PM
To: Zhai; Zhai, MingXin (Duke) <duke.zhai@amd.com>; devel@edk2.groups.io
Subject: Re: [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code

Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.

Hi Duke,
Next time please also CC reviewers in the cover letter, thus the cover letter can be also sent to reviewers directly.
For the entire patch set: Reviewed-by: Abner Chang <abner.chang@amd.com<mailto:abner.chang@amd.com>>

Thanks
Abner


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114667): https://edk2.groups.io/g/devel/message/114667
Mute This Topic: https://groups.io/mt/103975434/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 4776 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code
  2024-01-29  3:23   ` Zhai, MingXin (Duke) via groups.io
@ 2024-01-29  4:46     ` Chang, Abner via groups.io
  0 siblings, 0 replies; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-29  4:46 UTC (permalink / raw)
  To: Zhai, MingXin (Duke), devel@edk2.groups.io

[-- Attachment #1: Type: text/plain, Size: 1623 bytes --]

[AMD Official Use Only - General]

Please add my RB in each of patch and create a PR against edk2-platform. I will help on merging.

Thanks
Abner

From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
Sent: Monday, January 29, 2024 11:24 AM
To: Chang, Abner <Abner.Chang@amd.com>; devel@edk2.groups.io
Subject: RE: [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code


[AMD Official Use Only - General]

Hi Abner,

Thanks your remind. I will CC reviewers next time.


Thanks!

From: Chang, Abner via Groups.Io <abner.chang=amd.com@groups.io<mailto:abner.chang=amd.com@groups.io>>
Sent: Friday, January 26, 2024 9:30 PM
To: Zhai; Zhai, MingXin (Duke) <duke.zhai@amd.com<mailto:duke.zhai@amd.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>
Subject: Re: [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code

Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.

Hi Duke,
Next time please also CC reviewers in the cover letter, thus the cover letter can be also sent to reviewers directly.
For the entire patch set: Reviewed-by: Abner Chang <abner.chang@amd.com<mailto:abner.chang@amd.com>>

Thanks
Abner


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114674): https://edk2.groups.io/g/devel/message/114674
Mute This Topic: https://groups.io/mt/103975434/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



[-- Attachment #2: Type: text/html, Size: 5872 bytes --]

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [edk2-devel] [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
  2024-01-26 13:10 ` [edk2-devel] [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
@ 2024-01-29 10:37   ` Chang, Abner via groups.io
  2024-01-29 10:42     ` Zhai, MingXin (Duke) via groups.io
  0 siblings, 1 reply; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-29 10:37 UTC (permalink / raw)
  To: Zhai, MingXin (Duke), devel@edk2.groups.io; +Cc: Yao, Ken, Fu, Igniculus

[AMD Official Use Only - General]

Hi Duke,
The entire series is merged.

Thanks
Abner

> -----Original Message-----
> From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> Sent: Friday, January 26, 2024 9:11 PM
> To: devel@edk2.groups.io
> Cc: Zhai, MingXin (Duke) <duke.zhai@amd.com>; Yao, Ken
> <Ken.Yao@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>; Chang, Abner
> <Abner.Chang@amd.com>
> Subject: [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
>
> From: Duke Zhai <Duke.Zhai@amd.com>
>
> BZ #:4640
> In V2: Improve coding style
>   1.Remove the leading underscore and use double underscore at trailing in C
> header files.
>   2.Remove old tianocore licenses and redundant license description.
>   3.Improve coding style. For example: remove space between @param.
>
> In V1:
>   LogoDxe module displays boot logo.
>   S3LogoDxe module is based on EDK2 LogoDxe module and update AMD S3
> logo.
>
> Signed-off-by: Eric Xing <eric.xing@amd.com>
> Cc: Duke Zhai <duke.zhai@amd.com>
> Cc: Ken Yao <ken.yao@amd.com>
> Cc: Igniculus Fu <igniculus.fu@amd.com>
> Cc: Abner Chang <abner.chang@amd.com>
> ---
>  .../AmdPlatformPkg/Universal/LogoDxe/Logo.c   | 198
> ++++++++++++++++++
>  .../Universal/LogoDxe/S3Logo.bmp              | Bin 0 -> 964114 bytes
>  .../Universal/LogoDxe/S3Logo.idf              |   9 +
>  .../Universal/LogoDxe/S3LogoDxe.inf           |  55 +++++
>  4 files changed, 262 insertions(+)
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
>
> diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> new file mode 100644
> index 0000000000..4463ba58eb
> --- /dev/null
> +++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> @@ -0,0 +1,198 @@
> +/**
> +  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
> +**/
> +
> +/** @file
> +  Logo DXE Driver, install Edk2 Platform Logo protocol.
> +
> +  Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include <Uefi.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Protocol/HiiDatabase.h>
> +#include <Protocol/HiiImageEx.h>
> +#include <Protocol/HiiPackageList.h>
> +#include <Protocol/PlatformLogo.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/BootLogoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +
> +#include "Logo.h"
> +
> +EFI_HII_IMAGE_EX_PROTOCOL  *mHiiImageEx;
> +EFI_HII_HANDLE             mHiiHandle;
> +LOGO_ENTRY                 mLogos[] = {
> +  {
> +    IMAGE_TOKEN (IMG_LOGO),
> +    EdkiiPlatformLogoDisplayAttributeCenter,
> +    0,
> +    0
> +  }
> +};
> +
> +/**
> +  Load a platform logo image and return its data and attributes.
> +
> +  @param[in]      This              The pointer to this protocol instance.
> +  @param[in, out] Instance          The visible image instance is found.
> +  @param[out]     Image             Points to the image.
> +  @param[out]     Attribute         The display attributes of the image returned.
> +  @param[out]     OffsetX           The X offset of the image regarding the
> Attribute.
> +  @param[out]     OffsetY           The Y offset of the image regarding the
> Attribute.
> +
> +  @retval EFI_SUCCESS            The image was fetched successfully.
> +  @retval EFI_NOT_FOUND          The specified image could not be found.
> +  @retval EFI_INVALID_PARAMETER  One of the given input parameters are
> incorrect
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetImage (
> +  IN     EDKII_PLATFORM_LOGO_PROTOCOL        *This,
> +  IN OUT UINT32                              *Instance,
> +  OUT EFI_IMAGE_INPUT                        *Image,
> +  OUT EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE  *Attribute,
> +  OUT INTN                                   *OffsetX,
> +  OUT INTN                                   *OffsetY
> +  )
> +{
> +  UINT32  Current;
> +
> +  if ((Instance == NULL) || (Image == NULL) ||
> +      (Attribute == NULL) || (OffsetX == NULL) || (OffsetY == NULL))
> +  {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Current = *Instance;
> +  if (Current >= ARRAY_SIZE (mLogos)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  (*Instance)++; // Advance to next logo.
> +  *Attribute = mLogos[Current].Attribute;
> +  *OffsetX   = mLogos[Current].OffsetX;
> +  *OffsetY   = mLogos[Current].OffsetY;
> +  return mHiiImageEx->GetImageEx (mHiiImageEx, mHiiHandle,
> mLogos[Current].ImageId, Image);
> +}
> +
> +EDKII_PLATFORM_LOGO_PROTOCOL  mPlatformLogo = {
> +  GetImage
> +};
> +
> +// AMD_EDKII_OVERRIDE START
> +
> +/**
> +  After console ready before boot option event callback
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +LogoDxeDisplayEventCallback (
> +  IN EFI_EVENT  Event,
> +  IN VOID       *Context
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "AMD logo is displaying.\n"));
> +
> +  BootLogoEnableLogo ();
> +  gBS->CloseEvent (Event);
> +}
> +
> +/**
> +  Entrypoint of this module.
> +
> +  This function is the entrypoint of this module. It installs the Edkii
> +  Platform Logo protocol.
> +
> +  @param  ImageHandle       The firmware allocated handle for the EFI image.
> +  @param  SystemTable       A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS       The entry point is executed successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeLogo (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_HII_PACKAGE_LIST_HEADER  *PackageList;
> +  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;
> +  EFI_HANDLE                   Handle;
> +  EFI_EVENT                    AfterConsoleReadyBeforeBootOptionEvent;
> +
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiDatabaseProtocolGuid,
> +                  NULL,
> +                  (VOID **)&HiiDatabase
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiImageExProtocolGuid,
> +                  NULL,
> +                  (VOID **)&mHiiImageEx
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Retrieve HII package list from ImageHandle
> +  //
> +  Status = gBS->OpenProtocol (
> +                  ImageHandle,
> +                  &gEfiHiiPackageListProtocolGuid,
> +                  (VOID **)&PackageList,
> +                  ImageHandle,
> +                  NULL,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "HII Image Package with logo not found in
> PE/COFF resource section\n"));
> +    return Status;
> +  }
> +
> +  //
> +  // Publish HII package list to HII Database.
> +  //
> +  Status = HiiDatabase->NewPackageList (
> +                          HiiDatabase,
> +                          PackageList,
> +                          NULL,
> +                          &mHiiHandle
> +                          );
> +  if (!EFI_ERROR (Status)) {
> +    Handle = NULL;
> +    Status = gBS->InstallMultipleProtocolInterfaces (
> +                    &Handle,
> +                    &gEdkiiPlatformLogoProtocolGuid,
> +                    &mPlatformLogo,
> +                    NULL
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "Install protocol failed.\n"));
> +      return Status;
> +    }
> +  }
> +
> +  //
> +  // Create AfterConsoleReadyBeforeBootOption event callback
> +  //
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  LogoDxeDisplayEventCallback,
> +                  NULL,
> +                  (EFI_GUID *)PcdGetPtr (PcdAmdDisplayLogoEventGuid),
> +                  &AfterConsoleReadyBeforeBootOptionEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
> b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..137f4dcebe4ebd77d5
> 0f35ed3b31bf76c0f5f55d
> GIT binary patch
> literal 964114
> zcmeI*zjE`um)LP-
> CmE~SVz0nu`pl&EZ0BMdw`zPTz7I7nJn7S<c9AM=+F#*I*h((8
> z@E(#P2?7V_fFLD{^4IUnM<gW@;0M4V_(#;g{@cI&pMTypfB*Bp?sorOUjN5`
> +wK1U
> zKkat^Ww&qV|KorE^X~u3N19>!_qN-
> ~|GT%h?nVBU(cS0g=kD_#pSyqmfB$Q@dwi1N
> zRR($E@m+>b8NPPAr=1LsGRVl&s|;^4yvy(@!`E*2x|88ih9?<h;`L32cNsoq_&T
> Ti
> zD6da4yvpz<!@CThGJNfJGP-
> +zl;KH+R~g=9c$eW*hA+wFPKHMro@98H;Z25j89rtB
> z+U?~3-PfZGPcpp9@Fv5%44*Q5?Vfg$&E2C6&3~^lyvgt`!>0^i-
> KIT0%IlL1uQI&J
> z@Girr3}4-5KRwFplMJsiyvgt`!>0^i9m(sXygteBD#M!$?=pPK@YQj>J<98o46ic0
> z$?z`2rwm^m<@=+&KFRPZ!<!86GJMML)iHlQ%IlL1uQI&J@Girr3}0;#JbgXN>yr
> $x
> zGQ7#~F2kn`U%NNi{<qzu49%9m%Fz7xF2kn`U%R)*oeYmMJjw7X!<!86GJM
> ML)fL;*
> zqr5)J@G8Tb4DT|0%J9_{>FcAsKFRPZ!<!86GJMML)fKlS^7i&5!>bH$GQ7+1DZ
> ^J+
> z72Y4^^+|?T8Qx@gm*G=}udbSWKFaHp46ic0$?z`2rwm_h6?*%6l-
> DO2US)Wb;a!GL
> z8NPO(vi+aCM;V@Ec$MKzhIbj7|Gv7a_4p{SPcpp9@Fv5%44*Q5b=B_aQC^>
> 9c$MKz
> zhIbi0W%%l<<m;onKFRPZ!<!86GJMML)m7KGM|pjc;Z=q=8Qx|1l;NwZ%I}Zz`X
> s}v
> z3~w^L%kU|~S69tHALaE)hF2NhWO(2G`+xlGKIC(6vcBE!r~QBT^V5vUApbS9nt
> %91
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKw!SW4}S=h3CyotEP=os3Y0Y$K83)~9oBv}34!?n!~z5g1?E>SmO$VR1q
> #~>
> zA4A{{Yd@QWz<dEh0Rn{r^D7riAaI8Qh3$opA#jJapG`twzCaoZP7lZD`RiF_iI<O
> k
> znjhxeh`=gE%t{al1YQoa|9&etjk!+R<HO7N=Jm&(KTb)Gm~k5d*RKtvc;^Do6|M
> by
> z)u36kvZy(p*3D5xkslr^9HXsZ@)80Sg~=iam;yCzea#T{{B34We{<TnP9OTGt~vL
> G
> z<MU~u+{)B7D*<W!4S|}N`BM|;bk66Gn!Apt4e~)>^>ydIR6$NRgsJrfu3HO8?J
> o$_
> zHTBhk=Eu+Cn0cx>x?jI&Ij6aPz*}LB>lZX@{ObaBG4r%i(3Ft5IA-3!k$F>zo*!0d
> z;jCh9fxq6q+5Ytf>SE^4Izh7unM-
> 5l=~pkA2L(b$bM1Jy#`=N+VibW@1S(_Z&l(qA
> zj%}l;*o?3--
> Nf0<W*a!885YZ}j91hy7D2!isEwH`1kGcYwwXQs&9FhPbe2F*XwKYc
> zE}e(vawFq&O7Lbr`(pmBkxeUs!>t^-
> sT+E*vYvVGdEHAM)iLwuXW@y&bI4qJY<^T_
> ze_<vkG;btKPO|X}6=8Xj-zV#Dg#hqjt^a3w==Nd!EzZjE<6Bw1%=`ZSP*?t9<=l90
> z{~&8Tyr}D(TVM-f=CZ@{L!a{89Lwj!Rzb`RH5iWsDr(p7FJhnOS=d);HqX3Xc{)r4
> z_CNVhw75t5(5yR2pqcR#W#gQuLsY&qCfm)}KS<=9Y~TEeK61@S`}|Sass-
> _CtQPb0
> zOw62LTFaL>?f3f!`IG&%^a8$RY`?FsJzjoJl3bUXq$kNW3GSPwH1n^bcHO`t=4q
> a3
> zH?StRFDBxCx=M?DY4kCJx4QBLG4s69Qi&eEkLt>&8=jrAL`>P{O?_98O)Gd~44
> E98
> zyUf4+fs-8AG{-
> gJX(5@Azn8<ucN5B1%%KF!KDFtARFmAxi=;OzxuDK%XtcedB!{~E
> zPLc22s@wTdKh`STX$e&TTOD3Ctl8n-
> +^*owrjmWA>o3^`OC(4nGg=!o!><~a<TCn9
> zn41NC-Ds@~C)4wp-
> ?JZo(k&qUxT;Ro>1ZZ+G<z?hX)u0jj%C88(Z<Ryel=&@o5`2s
> z_ewoZNljK67DS(16EB;;Hsz1<^ul#*XWV`aL=@C!Z<f9G_&Xw2gqRf7?0m=qzZ
> 5f@
> z3SJ*JEs>z<<VNd)W*9Q>xSuI?duZ}=Mw-
> gk#)gBOB7Z3FS4nL*lG)9_u)nvDVY)mX
> z<VxoA^WkIZV@gi@?}Ob2+m5E}7TWX*!)8rGzJX<|Sn?AcJkQQ<caLALNyj&$S
> P{Z5
> zuY!zO+o|>g*Xd`Tx81LD>LyqsIn{9fetN=KO(UK;37PjDGp!(I#5ai!<GU}?k1GmD
> zO%GvQEE<!y=JhjA4^9X>7pvs8iDUBey`VCkzNh`mxXz5z(&IcFoAiz)>5a>6YRo=
> u
> zr$&?V?Xv>a&riH^t57!{GbNDKJb2d<31ees{PeSrjoq?)nU<OR`Sb%}W^VY{e91
> 9X
> z8}Yis(e{Y+rJx@dA5}$gvts7{drrAFaZJLPJbt;ZKFv!_!haX03!-#nu$f8IG42Y^
> z+p6GNLfDYb<H;2!D<|8JnKe<<5>Z5zS#zKF8=v=^SK#fZ!(7~H%p6sQe%!(9SFI
> N_
> zPx{SqW2VxvCY#dvtBIO(BW9a;6Q(6fdnRc{w=u`OOmkYa4d$wUlJ;aph<k{c5;e
> c)
> z9V}ZSVQ4bO=LOBEm$~@+=1CbZs!t0Rj`szNZ~71N(gmd5i+zZ`R?L*+<RI<x(dIg
> h
> zM9sNXYF_;bvLop|?+(+Wmbjh<AK%od-5H$M#-
> |%@Ujf=DVbChh<ipdX{3)yO)JnMO
> z`OKlR%&YO1$gs-
> HNWbiyO8?yM<@zO?75lKsC&K*viI~|4_yK99nE9}vMap?tiDF^#
> zhGnIVS9EEE`XIMIJ)2$4;IrErwW7(Q2iV$IfYS3xR$<;t%>4P8^Lt{Jh*rhbc@M>Q
> zUC5lQq@pT^%m0~}DNYh0tZvmRF>_fA>n=jg=xWwnLkw$7bI)l1E!?nL^yA@Y
> H#KhG
> zqFLPF(rq?_u~LPs2(cg=UB;};T(O_|BO6(MaAk?~_0E4S4Vp^Gq@S5qYimw&Ze
> uJR
> zrNW16D!K-=<hxzx#H1k^nH;m*jLpA-
> 7;aHNe#qYu(0^oeul6ByeNW+~i4WO7<?534
> z@w<tc4M_3fvL%w0P2VW{i6AXx5;JEu=X^X`A!aV^_VwG6&*Y@;)ZO0OCo;a
> ~lN&#?
> zwK4NjO>%X+c<ap7CN~<%YOM%yS245ryWp0{q<T9O$_^?mM)i0j{g^u^%uD
> ?q*G*>L
> z2QGOHXp)m`fLI<gi+8n?3~3YgS;lh#uF$DHr=2y?^0tk6=G6|TsPkKBcVD%;<*f*
> D
> zUoo@v`IeSQ7@FMif}W-tGU;dLD|qIe+%;9FA^FGV1!b7Yk}}&rsk!XISkok@-
> ;)??
> z>-
> 1Bbn#!MWkj+c4)s$_UeY3o_Rx3i>S<IA^nk9;s$XN4A#@yuekV(ueDW>UXGT~
> @x
> z%q%@CJ<UvZDwE5xF1a-(yK3c);n{-
> Y`kOK3lUtdUX)oRO)gGK%7hQhT3S>oyyNj98
> zvqSZ&Vu?&^pF5@Pq=H0qRUr6C>1dc0^Vqz(#d@v3{mDLZz1p$)ZkLHhYLy>N
> -F_x9
> zbHuuVG4n9G^5I720l(hMvLeJC#ms&)3wB2RN5e2wJ8lNe?zS)`xr*8uX3&b6*
> |S{X
> z3TBL(2a{KfnLGVN{=%4P?-DAC$-Hq=u2U{<ag#jhJCeyqHa21Q3C+fq-
> OyaerE3K0
> z-
> 91W^9h%JI60|l^&5a%Ohm0*4@sEBik=Y3w<(R*dHe0^=H^Ph^@*m5DmT>9
> 0<7zo}
> zIk;xb)Vqw!V&*!x{e-2FiiF&2T{9n2R73Re?gmH9bC25P8h;zj=B{_KtVQlIX6n7|
> zkk%3jYk1jsHfS2R9f!Fo91k;N^fUFy5-
> vP@+}H`F5hANmxS7VsRL?~*bN!Gh_qSW!
> z2!qntaN{jCHRJO)|CV`huH6>oZjl*<fAsE$6(R02W|~Kn4Y4IMJECMS=VeaNw+
> Xlf
> zoqiz9m=!Zu-Z)9tXy|E^y<p5#cLz&i=6bjNgvFJ+nk|x*C*;Dl$KzTpi$AleY5f$;
> zx%L}XF}so0J}mcGPOA~!R?Ivd(?9uzHu+hUd5_!jj({wYFf<j8>oHoZ%)<(^1)P6l
> zSXM@in7K3W)(BTpJZ@CftHw<AGSHHkX>3@&9Q=3G{&1^Zx<ir2lQd8MXp-
> vwH4;@~
> zjPdE)f6F|1=aja#b>{kVw=Y={;<jR@er}<GXn%yIJQ}1ADw$|nBE^v;_@LHb$=y
> %b
> zEjGzc*+h_@TuI3O=~o59h3Af+jL>r3n5lI%omQkR(gR%L$h<8}C5*Lc7F__62XZ
> z)
> z)Fyw;Zv+|VlF!vfsc2;t>Q+Bx_6wVzn49_67q|ABt36hP*h<W7%2)QiAEjZ_Xy&
> pe
> zOGJ}(=cPf@I6!OGR#9KwOkC^(2Ih5RrgnWRSL@HhM$AkLt)f)aMU*hs7EVDo
> ^EvwY
> zih>7rr4d@q)MjSpE_1KmYNbqaRohByOEI%4^s;CB3x;*{x^m2HeB-
> kLPRJx?*0o^e
> zd`ErE%(a)gtWB2EJNy3GOu4nT4X)uo?lYIt2tCQm<|gc`Kq1ZI@ob6QQ_Pg8={
> ~u;
> zl{A}@B{HuZ+BLO7b8-;nh0MPjGhgKVbo6&@&fQ7NF4%u7&B-iiS!o)C&L!-
> ezZpY~
> zoEJJaS(bdZ*(}JX{?mePkj~s%>mAZ32eV_|H#wGU&%8D{<I~xbfmVblDSy-
> 5+P+B`
> z>DOYNlFe>Hzi|8de6$kn#jFZyiS*0QeGN~JW$J#g%E<<mO$19{dDNhseQd7X_
> |crZ
> zEBxi<wB)N}X2F576pS3$4A&neo9%B>7Bm{AL!2CoB*mVsHqKY#liPrkHE(N%
> R!1&V
> z<@FnlM9Yd01;uZBr<Hizx(mfjsmS`V&zN#Erl#I)j3qK%$&9J-
> iDKEhKd#M2Ro@*K
> zzV_IqV`jHK1!wN$3zW&W*T&4EZl?0fJMznvYVkxfm3HBE7maFTlz^n09Gpja+
> 1zCI
> z*dQtWWi#@1z={ytjG6M3YN?afc8R6YX?2!t3*t2M>fFOa-
> y2B#UTMizRO56d*P3Ir
> z*mPT+?wi$z(C^urP$gX|{Sgb}GTCEuC!ft4w6lw1UKHGwj;51hN;#Hqe7bzxzIH
> 4Q
> z(9zqQn@snNBgL9y`4X`r#8zWw$wRU8{Q*nlTqe>mX8)b*rWF?Y60fMn{i4@
> @y;jWh
> zk6w3aD5~sd=DQd}(d7Gm`+Q>?mX70?yK!cqFp5A@jIW#znb_!va@zV5wce;Y
> R)pAW
> z%q$3+`HrR~(icuav&huQv@g`Jb9~J#YRw)OzV?{WVAIZ#<7V$rvez+tnB*|Dwx
> 8)_
> zQ_?ejJEG({t;y*lqlGqGmu^{D%r?w1s?fdGW?z#XPH3^(xKXbo&`FZpjhXiMdfSc
> 6
> zp3$^KdLF+~<!YqaVK}cox2!S0&)D@}jk>jR%(PCZv@~gCaY9k%*xZgmO;Tx(HiY
> +2
> zBP0pucj4`p#eKyvH5tzzG|AGjO1r`>|5MWKh=3|4v+>~`uK{({!M&j;+tx1|GfN7
> *
> zqC!_xij@}0I?5@(q(|WFYwUie`-SZEsI4w$IswcJnF8x<XL`VFFA#^lxaiEK<M>=r
> zyKZcek`@{h&7HRDfR+A+`<dzPHAc%eCrhMXiCIa_8b-`Cc!-%g4l#4$;`F-
> vM!M+r
> zI7x9jVMT~d$4uqUlPO{@?pY%J8gk1{ZM7+4rlxY9=fuqHm)XvX$2}^!ifvcnbb+
> >j
> zt@hF+mG+<edeOhSNB8l;y?J!)R%JWGQE&f@wc!`*F7Cbr7QUV=9xFoF70z1g
> `Ms#L
> zCflK&FR(PM-
> m;n(XLpo)M5!gxZvip0m$2ek8e1GUFJ?MbV5MVoC(xz`)`P`3Vw|yP
> z>uMCOofvDiBS~}K(rR1T)=bA^EQabav;3?GvGJIhHlZn@8nx{+y!{HCwr|wH8|-
> JE
> z9=^-
> |)T(OKuGM3va}Q8@2<wEuC~}=k*NM!|1)%dv?5<xNckO)Y+3f40+nbL14o2n
> N
> z%3CEDQb(SOF}pnKW2QX0^1HuNJA<t@vhyaW5o^_crgun_Y3-
> Is&wp1jGvkn!X&RHn
> z!&rLtm}yt#<O;DHP4r;og*&TO_Z7sw#y{P6+B*Z)eMrgtf<{w__ZKt0-cVpuH)`)T
> ztq5WEGrL%CuiUC#SBRO;6LvEP=axuc0(TWNi#JBCs@IH}c4*n9dt4{Tsxi|!(p4gJ
> zUn|1bd288!91rb-gw-ZDjjv%U?YNgz)GJH(h1;9+;C;_8L7F#14Ne1-
> 6(Q6DJTKXw
> z#5S7DPJe*QIrnO|(po=ms~w()4GKq`%BF9hCDP}nILw5(X~&%`wFx8(`7`>A)w
> ~vO
> zjN0EZD!}UfOs5J&!9gr)Vy2Tw+-=K=8!l~eCjE)#VI=##d?{BB-{d(-K@5#LigAiw
> zO3~teWxD-O9AblYr!&2&-
> o=U#dQ54T9GZ`L|87z*f=#<d%yc@M`azf_(&xW8%=FB|
> zD=~ARNJqS;;6#TgI7ngD#7rj<wQt(ji{RDi6Z@fejG^{ZDV+0T_jqi+a~gI~3{|5}
> z^R^;HK4u0L$2v0j^_ZFVJVHagbyy<((hh1G4Td?_ikYX9&FD6#cw>egWzW#O>
> WJ<3
> zuHMhocXESmTHR`5ro-XI^}*&a<Vzi~tLCs4cf@-
> jQgXDX=4NX%*V0pYomx}*EV!_C
> z8bLGsSe(17^fT2na6?Y?E_g|>aoUwp1Fsb`hmCYc%p--
> #mi%_ibi#v@J*V~uyZ(X6
> zc}kGqKkV1!)RE%Y+pkZ3t#}~Fq)4|qp_KLLQ}EO=vymI!fY!@eINQ&h{?>fHD*t-
> S
> zG|#AJo}y`q^yT8T2csrlFJ{UuMA0+P^~qzlnB&b*E2>e!R_<qdKhdM~J!)d6!(r9
> w
> zzIwE;222C1Vop}zPwc<dp2xJ@;vK{E-
> K|bp#juxO<#hhcM(&|n3+HN2{8W}~?XWgX
> z&DhG<faFn{X2nwvpVG5p={jydW<Gr6O0T|^sLecE_}cen95=J?<@JZt2winP(>
> V_r
> zN1(KB^mA5QQNP0I_4H7-w~I@yzWi@#NvmNSN51Dx=&xW$q}`-
> <5wPaiym=1RG}Pvr
> z!tcjS``}#7_j5teR2M9&QdU{_C0Mkg>4*A7yVujt1tMmqYjmxc>4i+S<5tnnbXr
> Ut
> zfu```l-F{t#u2VZ9WVX452+<__j_7#wmM}tY@<$g+iTjZJ*m)X8vLf^qxV#jr>&lT
> zaz{;8)~?gfv=7ep_MvrHrZE0<YeM45_;q5YbFpNSqsfGMNE07lv?xaXOd*|pO}?
> Lb
> zdQj_2n0IYgR}nLvES8ktxw1HIPs?vq&Gbn*>2lDUX2>y&$LS1jY<nc$tkBB*wzz
> Dz
> z8F2Nh93j^1n3*;N$!%tzdIK>t-phuxKN+56uP|AtnQ$6b2po-
> <w7F=JlF4ZfYqKZ6
> zpKbi<m*OuTGv%(u?+-U(>fdOrh?&mr#%ik5LhveySu>+m4U-
> ZtkG@4%W0I2z;hP&C
> zw@%~P4-`$i-
> UDwl;y0ezF;lNJdN<$(VrIVUB0RbMksCC9*IaG9M$FW^&$%20^WBGz
> zPAXS7v1ZInf2;R+kbApJI#uefyypJQ^?HYfOk+MfX14o|5{sZjl@ltHcQ-s?+_idg
> z=#53aD${_?jhVTUR`0C6ftYD_!?Qm>=>^T3j+vQGe?jxGW2RnJjOv-
> jF~^OVsqB=7
> zS;Wjq70yMX#w*tu>Q-
> QOQH}cCC$BezuAG#8TK<BQ)*NmiW|}*NY|Px*(W9XM-uuR{
> zSLkQv@BNB16Hhx^J+$6%#HeGlV`iM68PodV&-`O^Z---5>5xUn4Vh-
> cN@~Km#^$1r
> z(jI-G1jb)v8=o+HL*^Nlgk)sSon@Sm%!`>;qf)YIRWS9ejI{@-JmR$SV4U}`ua9aw
> zhzV<UqNJr{7tX&Cl)Bee^DFW86k#I6xDgrV#!Te`l#$uVTSvVf|7y&1D(qn(^hRc
> 0
> z^qIh<^?363mM5&1ZP}Z_)>^Q~((77RiphR0Z3IDaD_@|nw(43j)7q*0C~>}rX?
> oOI
> zoSTlB^_jDFi9tzEMpulPJ^lRG+~H3}%uFi%G&fe2p18P=Xe*7G`&n1Xr@2kOY%
> W=h
> zKe5?q3(zWf>!99>2m@3$EQoGWea!gtvrodHRl$-
> EH(9zsKhqSl!b_&>(l!ihxq((4
> zxk5kF*b%5%8fR`bX68bscS1k8rYyV3q|%Q(GNvpMMapr~xv4$v0gj6fV{%At
> XK0eU
> zbV5la{m@qDSeJ5)7HTbKp9noe&54<2_>p2xPNdy@%rrVla>6NZW0Z(f0g0Io
> P{rHo
> zeWPvInI8e2KzH4kS@hjV6HMvln4jO&n^ru^A7fknva$;m`M8kuGmRK>-
> Y>=>=oVt8
> z)q{6V{pB~9m^t)>;xZ3fU3w~~-Yr;dH2R{%g+6!d$4sle^r@a-oy3(c;B*E1WnIjM
> zN$Y?|d>fuLqn~;l+ia{+UA&`=vz1i`rbh*C8B2*rZQ>SUrU`2__{JyOfr+;BY+3R`
> zKeI%s{4>uV=AqWK3dgHedW}v$v!oI9k#AYdTp?oWKad$CY<Sv=FS#aaUIB9A!
> I`Q!
> zW;XT9`fyiM4wDkFwn^O&SOG5I+n%HuPgtvT`kDFrj&lVPC!S6dGgFiLId;UXIXij
> 1
> zm}xfNQ^^yHJU9Kx3Eom0df#eHneX`7w|J>RDFLy<;AAIl#lL>fDwTASs<q7IgMG
> HF
> z0QVa)Q@*UB0ueKZA~$x;7d|$Be)+H}Sd&Ait9Rjkrdq}Os&0PiS^rwyuxQzc9y
> 0Ie
> zy1Dbc@oD#MAhW7WVTe&f!nr|&Wp14X7}}4FO!m`O{=$_H8+3CqGxH5MV
> &+ihzZ5f{
> zU%nr#y4&S%e#~^1Sn=3A-
> _Ja$U#c4#N#RH)WZqNEG|x@y71J!h!e(vNyP%(GU7{MA
> zPdgIE>N|*;da)GZDz)1>oaiBy#k^VlqRs1F-)kiIy^DqPFs+I^XgCp2>1R$4loIxQ
> zpc~R0Mkd{dWKHU`>)K`a^#vHDl6LaX84EtM`BAHnrI)?c_tTe1k*umWb_KQTZ$
> sUP
> zMuPZ$4>3~>n#9bZ(1YTRYggKA>)nQRKffI0G2AcHp9&aq6OA~n;3i{cdYkjG?K
> 4L5
> zPfVDxlH32NbpcR2I5+osMpd3jSTS?xXPO<_sG5cs&u<}S9+Lb8Gm4ayT~mGA|
> 5N?U
> zq(;}f1(o)>{Uz|CuIBnNGufn|HbtZ15m%7?el*jl)(M%%d_Md1@8Z=u{?!`yQN
> KRX
> zmYj2lF?yB6%(lN^eQ;V?#xGIcLd-OSR8bpNP7D<-
> HzEgPW_Hew!N*HS!xE@Jv|IUm
> zKxtH{cbh_VVbi?LsA~qpZhyM`d1`(?(|(3^SPJfUCsUnf@v-
> r!IWC)N_QK0nv5`+b
> zPst}!+78o-NX|ZP6tO~Ke{60gG|A<8V%Sw$3-
> &7?vm#^G`HA99nyfK%5$BxKvNoIs
> z&9ddD8R@3}Qp`+mZ>@KWEt{yhd-
> jgdwPq8nNr{=pV_Vt<ttuV01*gIuqK~(eYlO__
> z)ICfp*#0{hwaO#yJXrC?EBO)2ikat~v|R*YarEQ;mnf|bx>n3oj;#A^{**E$C+6zg
> z{vV2&iCTEtW~_mAW5mp?+n<V=>YnG^z|)<U6%2AWbf(UJ%*=m-
> aEv|UShv3Osf1gI
> znN}Y1&(DmY;^u#^G1J771IMwPhcWG}QKzR=(0aG1K$^+s3VQQ<e#T!#KQrx|
> Op;bM
> zDwlp<rd^}f+T9<Do8(2Ecs@9Vs4lhLnMMUjPEeXxfXeHp)(rYe&~^p&(=Po-
> a<5$m
> ztkSzyKhrQxzEPjAIZ@Co_l;M1)BQ}jhbRB{{r#W?&1_`Q_O<nHv12<eLDN13TM
> ;vz
> zELs;GqQ;Pw>9$2%Q-
> 6S_Zf(iTXa6RwlGSYJGuBQlE=#NNIaMVTv0`R(Y_6U1iRy+n
> z+5Hmb4a7`y*D}Lt>JS%3C~A*e#nwaGYf#_q7j0gho|3wJ(M)ysnTrhS8J#+}^Eo
> 0t
> zkNKNwgu*G{X`yz8x$QZpUQ&MDio9}A8hg?)(l<Ff_r<>|c1O?8>=>+5l<~p26_
> 1>9
> z56!KZ*>nZ1WX^R%eQB=)SqopOpJ|cies?nT8OA4Vv##wo>ndq;Lz?9yVHsR3
> W~%!i
> zy{@H~&DtC~Zik2H@B91X=>4RF)zhqqnQ=Rd%0S(3g!;p{7XX#U;qXLRi6)<q-
> W9Pf
> zYtdqxpHv)&GMEM#tL(he3Ynaksq74g3|S+mpXMvG<(qTPk`>{c${cP~Fs>Z|4H
> =)c
> z$}niwSMJ}And$FG1X#|f8Z#f{4)f^m<@lXBBjUInhLQ<J+{f-
> 3U%04<na;O&w61B8
> z*<jRLQQA11C9KkUIX+~_gB*3E)@ru+p4FnJJ9I0U%?Slo%zU<Q)JaNXIz!IQq}5
> {l
> z$aEKQF0A!qrj>>G(REIZ39dIdZQodtRl+@vv3TySe$nRD>Srn(<+r!w_S04!3Nz+j
> zH&<h(tiky<p?VsiO}HXvdL0f$aJr5Cl+y~89niFe=ZZR=UvztapRK$4zIkJzKn~kF
> zy%uimRjfu6i(B>m+1P^**~*W6-$Kl^wy*S7quy-
> f*lNsFdr8F`lZ%=8DiFWpB$bPq
> zKlb(H=mK4kXhqEQDusFA5+v>IkW<X^omXEW<yHFhWnaA?vKB0SAEQ?H@e
> pjH)m@ne
> z*I*%S)QBmkpkp<NmyL95JzD$Z>-
> 00Tt+3e+r$wb)L(p{Ee!Ao^$11qqcKC4lNWW<F
> zYV0z%8Z)D348|_UTrGA=xP~K*b)o$@?nS_~X3o86{yaZkHrb2uHa~40oQ7R
> @D;mve
> z(7D>y=vwbJ?|XkIYX#SdnbtnY`Q>=6F7=Ib7V%_7#LNlDbRvx-Llv`+baTz2CT51s
> zY?{4pDwo!f)o#Q)IhpoX=Txf7c-
> dr4+oo;LGmg1~3SfoS;9~_8R#=N_K|FbKANd+D
> z5l&wxW}2JlwGM^veCljY^`5SUm^t;BOc^oLKFyd0psuPpZ9(m4+R-
> `x?EbKF%eYrX
> zlF;jQOb4k2@v_O|u%5da$(4Sywd29L^{IK0zzix)qWWL6*hl^mfcip{xmSsq5}}L
> @
> zG!A03^{ES*UW3Rk{>%3osX?N6V@eN8C*?euaFQ}&ru{P{xt!I+OglQ;*Br);_1
> 2Q+
> z*ju8lQw!r|lfQi3-0C~lRiJSXXas`d?*n#1)|$o|pp7-L*{bB)GQqs7#LQ%89%Nwt
> z>C9HF-Ca3t->7^N#oa$+@!VVCI*na{8Z-Cl-
> 9pjLL*3+}yC}L0I&M~V8Y{nMkSXYz
> znCbQq&GS8dL3llvv>tc|^AfG+T_EqX61{4C8=sdc{bs|58c<)i5}fLo+0|jI!yA=V
> zG<l7fX`RB5J6IBoq8ZI5J8j=sPuf-
> @7nw8`&%G6{WNyq1m%Z?~<5pj<Gxcz2F}j<&
> z3;D65v-
> fq)PH=d%m!7cpi?Lp^yW`9Y<e9R}<!Hn6t$Nc}xhAgWf}PP~G?m<HGT_7P
> zey>=x(;b!yMy?Svjs1`0q}S9~ta;KtYZv|P?*ZvSA}Ey$k2-Ev-R~=$UNY&SZo4H_
> zG1EOr?ym&qvAVAg>sf8*Dh1)h%<wA}lY~$EQ}Z{OXH6Kn+U#4#)}L9e<M-
> 3d?KV=g
> z;KzDp$EEx_t`IY&30j+{=AeY{o0yp|SM!|(G1CqyYsO5!blr}EcVw<z39y&Re?#;^
> ze(B@o<#0I4<5lE2Di05PJBXIl@U4BuDv++3XAVT#+UnHG1j7m{+3J4^E=MVQ
> %<OXE
> z8*0R|4yNr!lWbW3c#-
> S|&R*Y`#P?j~anWOFkQpC8T|5@9$vD!eEv#_$OU4~HtDk8X
> z7cuis$4o13bal?SAL++@28_}KvmwQ78e!efR9AC(dGqoy)7tq+2EuJnV60i~Zy#
> D8
> z$iGL-%-fik6z!OqIrOSJHg`{G?y|?p=SuJYJh{^CG5eYMuR2LR9<JCmwC#j+JYTvX
> znznDlf4grPN4xE13u|v|!fPa{sTb_z{b?#ze)223c+7ON<uoVFYK?isOheHsvT2=*
> zSCZ*KJB6HEO0An=l6KJaL#CFnxq<m=)0`z6f@X7+{u0~<p`8N=x8rWcm3`0<dY
> aO-
> z`cH?s3N<k^{*srK;UVYoh*~eLKDOP_NVYqF0;tQ0Sw)kztu`ZH`A49N#Kwi^e|Iu
> m
> z_QK;%-`<Fs-W}h1N24xg794^Y{l1@X|5#6JF=qYFw|V8-
> *cd{!o_j^@y8T5m#~E#P
> zmX>b4ZMv&lUJ*0XQp%TTz71YDW?GfH&6JwHO0?=sVy3}q#LRd<9j|58nCXP
> tChhFc
> zx19<?rdm18wySSmQ<3d`zY?5dx%-
> $lLXcb*R~UxKWSsub(9DmS<0bQPmH8qavKEi1
> zF>AGcrdlh*ESNQP+_2Thh?xdyK4yB|%*-RSoZzP&BDa;q=?}M?aL{g-
> JbkP6I@)G+
> zJJYU6uvE5zX{|9>P6;K!yLU8dMUKNRe+B5|R1uA6cFa_7J$u>DUXNP0tSz4t<
> =l{|
> zUxLzrR-Q-9G(go@(gZR4S#Zr7^`PQ3h-}O><5#-
> @avAVBxygM0P<C!i&8(SMCH8ea
> z06V&C8)*1%`K^3d{Q0&nQ``M?Rb+Oo(+kPURadz2zn6@e_9^-
> %CvyU@>Q+0Gm}$u6
> zV&;Q;{G<g3DP}Vc$pLn@q3N|e%(`4|ksBjF<aWsRmh#j7;rrm9$ZXe;X)IQ}9iB
> oM
> zH6tguYbk{raYy6E;rB`1M|F};KV1cy88fqIYx2*^j!L<oykN{UpWE4{Un3Rr$yxT`
> z>g0IN-
> 5)cGwwK|%lY>Mv;{LWpQ!rX^XqL63SUzStv8b&Jayw6Zjk<l6>JU~CYdm)l
> zWcGOUX77DPQ>$%O);9cJrUp!^k}^@#d72qB^QYpoM-
> NIyn^_l&na>5`+pL~`#d&VN
> zZZZE)mdgE5&IHNNK=O%jd81R74-(-DE;sIU-(F%<`3<#$T2W$vOpB?Gna-
> t^bMnvf
> z^_%mpJ#mJNX)Ta7<Yt^!51sZ_*R;uj7HN%~ZTc;3Tm72s32G$sVy3lUn;A6Krm
> *~c
> zrkrH*p`50qIfe5wKdR`bTlk4Et-|qe&DV{Yr|;}vdXdD5nS~pxd@K`(oPsuXA?`(|
> zb0)eY3nfR{S=pQ5?1P_lG5>m#x+lqIY~yc~ob?KuNjqNkoSs=R)2v9jLyjb$-
> HeOG
> z%;$ssd!@3q%?2-
> Px|a@_+d4Kky6kC<u;G(48|AGyv!kq!nLqg>s`6Z^pUn3yY@L^B
> z)js(rdG%Xt)J)yO%vquA9F=VHj7o7rO}MdBQ1@z?h<TA?^YlWdo_ftWjDRm+>
> GkAh
> z&kfQl9SzgCZa;Iym|429>F07)Z$Zo~J33FZ;>|H0iew&~%a?t|D^B}|5ASE+B_H
> WN
> ztEnbl1~>bDMZ0wBM~0#}W{S4aJleGz)gf%t-
> T2D=Ou39%bgobmw~v7`PUGx~qDi;j
> zoHM3XJQl9cj+t``JY1_X-
> mc216lt5ace=$}n|v^HXkLE}NVZnJsV+%*?u_&hJAgHL
> z+6(pVGmJ{FH|a;Kb920z&s!(<0_1SisJzBz&uBt^_bgX+!)*5BtHn$?qI)@fr0351
> zgpyYyrWjEDTXVKCNxE!CpVW-kaK+a43Db-c57(L-
> H&VM=%uEwH=ho>*80Rx(1?HKk
> z8D$fGRK1il&^jH>;fhnZ#{76jCBMMd-
> ^rYy8F<qXH3+#3<t@lA&@Q1FeK0k<)~@1o
> zjQ`|;f$bv$=iN|Ww{PhouMje8j-JBmU_`N^pCby_<%~-
> NHg2&=8?D)q>WSyS>K!V{
> zyOldh#*Udk))mkBnQWFwMW(=>PkY9<H0exLEnR$jpUZ6UlsKI7dx0uKam*|`
> qAd^g
> zvtwqsvAJ>C8gGLtoz8f(izSy+Yra}g_RMf~R?K|<$lk^suA+F{e1uOLA-tGiZ)EP>
> zG@U;G%VOs0*MZ!thh>c{=P;e0Q<;A1o~EoPar8A}@@lmd1I7z6LmCHTCF5Jp
> o_knZ
> z#WkQ{*#)B|z2$Lp;<2lQ%uDt&WrNzsg{}0D(aDsQ(pF2%w5u*LGj4ISre_@HH
> sw%t
> zqmg8&G-
> j68_S_ZBq^?|~pP8f*&sbI|uM;va95ZLt!bKmxR?N&7%ff!<+8s^5O|N)|
> zQ!cSZMS9x{=e~OzM}hNnX-tbZx*%pYA1OZxSeoxE#>{aWmxaviX|qh3)Xt8}s9-
> uw
> zs`7}VAeEUPxl+tDcGF8^=8t*qVJ=55iiL$&-
> q4)Xvp2Cg%WeAYStp*H%8`c{<4IU@
> z@%WsRfcd@tWUW_>nM1k@LuQ%PkXrRfzO=IMglYY;m}y;#cA7=OnI!k?iP<8
> F-*8W6
> zc4b)G`H7Ot??|E#-
> qmDb?CGSdcTXj8VCFOCN_MBeaz1m}b<pgNJB(MWj8|0SFx|fu
> zGt<s&V6i-
> Au6CQI721OwdtV$WtQ&?(;Tksiu~}Dv)LvW3W*5cGnQJe)c&@I~y4NVI
> zSo6lu+qmpF>(H#FL~CB&v`?3mTlAT5HGe8*+P$|GVx|N!`$|_-
> 5}C<E@nNI$ZM)3+
> zr?ag9J^kdJO%;WnuCdHHcAhGgM1jL}5qGNKkmncrnFYT&U~F0bSSJiu>x>)O$
> h{RN
> z{Fh>;9Woc*pV^}>+u1fnmi;A+K8eZevYIN%nO`=_RiV3>KjV@^eKRSDne)%Elm
> wV7
> z_cIsv7D~2gQty{cRMg%ux%$dbk+8K$dVn~;Dp~87;NbKt*63#nZBu!cbT$u8H
> p9|u
> z#uo<ZquHmmMK}I#`N6qUH7o}|X4af4EeQ8ljG0mk_sar_x#Ny&{Nib=yfW{FX
> )fE;
> zOae8tFCH`P;2<VW!zel+YH6Dvttfx0@DwY0AW>LUx$(X1Txx@~_x#vt=I(8(>|%
> <z
> zFW7y%F|+QDG5-SAHDjj#q(QstTsLHLf2Lg;{ksLRXtkL6BUMQHniX-
> ZAeUO?Y`U5?
> z$?e=eZO?a~uccQ+mfS+)#mw4k&3(MjuK$WL^I_px{ItKM)$;Y`Rn+D%@xRf}b
> e@#j
> zfvguZrO*0sl#n?yj#WlX$$h(@pPAZDB4)P1^;M*zc5P{q!qXr%N6$TjLtOoA7d
> Osa
> zEoLt5WV$EK`pUT4YhN}qUc<EiK+G(CQtFy9Q;7E;YOT$c(@XNhlwmQs<EP>u
> Wjkk}
> zOeL4wJDKkv;kNK{uBH0ViJA3B{r&N5E&;XnmG-
> RN`Zjz(Dqgisx1byShqTrjsmO4c
> z^nJ(7=a=KR-
> <djltQ<3&&SuHOewzZ62L$J;epp!c_`W=BJ|7F8A6rqowzNpuRiN6h
> znzs^mxi0C!$_<Uy%C8bLXYZ=h+Tq;IV%Pb)chgL`bHapfIA(qy7W^IC2mj5AL?<
> UX
> ztAd84;rK}cnf;LTna^_#SDuVZYDYUYsT;B%c`&b)hpTn#(#AhfbZ}nZ7Ze?{*3{qj
> z*|^)i<jcp*rgB%Dw4YX)UkI6Zd<`gUyIUSV$uEe?FJi{Et9|<QxBTMyy4!X-
> b*Uw1
> zH=D<8A3vnqJtx6w{l34ck_TQm#~%)grCoddr%$rK4y4wgOUKOp!?&75pSiNv-
> w2t+
> zOtr$?-
> ptd!`E6nO+073bn$i7!R`i;;MW@qV(rbU@v+HnIrdL++H~c9pq@Br^96y`=
> z%q5rOJ94X=tOm4|&Sy3|=H*??W*f|~Kd;W0f4ZW+hAY3}WAiYZ+aD)pR@Bt
> XFJd3x
> zw$)AzKE*l9p9WdsH>9k4hShAZ5HnBf1x)Ys!lhb$ap8?0470N6T+O)3<zv^sdK
> NM;
> zt_v(L*Bf7hA4Ha&b2QFpuF>?2uN<l|v*cWaUK3=lL`&K8f2`BNZ0kkA9xI!h1#e
> W;
> z$uPBL2ObrP=N9R2od`3>_-_m3O6z{+%lTdVZ{d-c-p`a%0_(KA{Ff-
> znE7IFtMRU!
> zzWgY?4WzVo{8GqVdOma6&v%sK6nyS_PtW`9IJBko3kq)IACX@*w*MAx--
> Dc4PXFZi
> zcHw&a#Xr*Z%Nz-
> QYRudn?2XO5n_N)rQ(yG@TOo64%*@a(vZz}4S55|RDSZ7(UaN|d
> zg%BtZ_%LrTy<~MS$Xxu9Np{xS-^Gc{oNk{uI>{IlHy|*x6!|y;r2_f03Ky^UrCAI<
> zH_g)_c<0wfxdJpTlv|nlwF*JPcP{Xo=i(}8rw#HZj?TXe?vtBlo2hFERMajOLBJRI
> z&5*hDe5N$Kg%7RuecVrYPjS3PbRZ2)z%4pHfIx-
> 7@1BaQ$ndmr$T$6e`S5(+k2y?p
> z&(uW)Dry&tAm9lYx0PPBI-
> ghWWlwoO&DKNmZD?h&3(caFnU=@R%(+mRv)Vr`@XH}{
> zg=6!kfyyIFKAgw;T;%QJ8V^CcnFw=#8Tr#qn~lGW!0#TIOCzn=tov))Y|(`TDry&t
> zAYcnTU!?mrW2JWX)ORn`zF6)338?jlnF#zff%|LPY|(`T{#w&udl66tF4VqQ?fnU
> ;
> z^@o`V{5665Yuaqlg#`Xu(_niMPz5g3zF6)338?jlnF#zff%|LPY|(`T{#w&udl5hY
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILC>Q
> uo
> DNG4Z*
>
> literal 0
> HcmV?d00001
>
> diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> new file mode 100644
> index 0000000000..b5eacfc5eb
> --- /dev/null
> +++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> @@ -0,0 +1,9 @@
> +// /** @file
> +// Platform Logo image definition file.
> +//
> +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
> +//
> +//
> +// **/
> +
> +#image IMG_LOGO S3Logo.bmp
> diff --git
> a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> new file mode 100644
> index 0000000000..25b46e4bff
> --- /dev/null
> +++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> @@ -0,0 +1,55 @@
> +## @file
> +#  The default logo bitmap picture shown on setup screen.
> +#
> +#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = S3LogoDxe
> +  FILE_GUID                      = A3193794-FCBC-E9A4-1AE0-DAEA9A499808
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +
> +  ENTRY_POINT                    = InitializeLogo
> +#
> +#  This flag specifies whether HII resource section is generated into PE image.
> +#
> +  UEFI_HII_RESOURCE_SECTION      = TRUE
> +
> +#
> +# The following information is for reference only and not required by the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  S3Logo.bmp
> +  Logo.c
> +  S3Logo.idf
> +
> +[Packages]
> +  AmdPlatformPkg/AmdPlatformPkg.dec
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  BootLogoLib
> +  DebugLib
> +  PcdLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +
> +[Protocols]
> +  gEfiHiiDatabaseProtocolGuid        ## CONSUMES
> +  gEfiHiiImageExProtocolGuid         ## CONSUMES
> +  gEfiHiiPackageListProtocolGuid     ## PRODUCES CONSUMES
> +  gEdkiiPlatformLogoProtocolGuid     ## PRODUCES
> +
> +[Pcd]
> +  gAmdPlatformPkgTokenSpaceGuid.PcdAmdDisplayLogoEventGuid
> +
> +[Depex]
> +  gEfiHiiDatabaseProtocolGuid AND
> +  gEfiHiiImageExProtocolGuid
> --
> 2.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114679): https://edk2.groups.io/g/devel/message/114679
Mute This Topic: https://groups.io/mt/103975435/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [edk2-devel] [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
  2024-01-29 10:37   ` Chang, Abner via groups.io
@ 2024-01-29 10:42     ` Zhai, MingXin (Duke) via groups.io
  2024-01-29 10:59       ` Chang, Abner via groups.io
  0 siblings, 1 reply; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-29 10:42 UTC (permalink / raw)
  To: Chang, Abner, devel@edk2.groups.io; +Cc: Yao, Ken, Fu, Igniculus

[AMD Official Use Only - General]

Hi Abner,

Got it , thank you!


Thanks!

-----Original Message-----
From: Chang, Abner <Abner.Chang@amd.com>
Sent: Monday, January 29, 2024 6:37 PM
To: Zhai, MingXin (Duke) <duke.zhai@amd.com>; devel@edk2.groups.io
Cc: Yao, Ken <Ken.Yao@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>
Subject: RE: [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo

[AMD Official Use Only - General]

Hi Duke,
The entire series is merged.

Thanks
Abner

> -----Original Message-----
> From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> Sent: Friday, January 26, 2024 9:11 PM
> To: devel@edk2.groups.io
> Cc: Zhai, MingXin (Duke) <duke.zhai@amd.com>; Yao, Ken
> <Ken.Yao@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>; Chang, Abner
> <Abner.Chang@amd.com>
> Subject: [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
>
> From: Duke Zhai <Duke.Zhai@amd.com>
>
> BZ #:4640
> In V2: Improve coding style
>   1.Remove the leading underscore and use double underscore at
> trailing in C header files.
>   2.Remove old tianocore licenses and redundant license description.
>   3.Improve coding style. For example: remove space between @param.
>
> In V1:
>   LogoDxe module displays boot logo.
>   S3LogoDxe module is based on EDK2 LogoDxe module and update AMD S3
> logo.
>
> Signed-off-by: Eric Xing <eric.xing@amd.com>
> Cc: Duke Zhai <duke.zhai@amd.com>
> Cc: Ken Yao <ken.yao@amd.com>
> Cc: Igniculus Fu <igniculus.fu@amd.com>
> Cc: Abner Chang <abner.chang@amd.com>
> ---
>  .../AmdPlatformPkg/Universal/LogoDxe/Logo.c   | 198
> ++++++++++++++++++
>  .../Universal/LogoDxe/S3Logo.bmp              | Bin 0 -> 964114 bytes
>  .../Universal/LogoDxe/S3Logo.idf              |   9 +
>  .../Universal/LogoDxe/S3LogoDxe.inf           |  55 +++++
>  4 files changed, 262 insertions(+)
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
>  create mode 100644
> Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
>
> diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> new file mode 100644
> index 0000000000..4463ba58eb
> --- /dev/null
> +++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> @@ -0,0 +1,198 @@
> +/**
> +  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
> +**/
> +
> +/** @file
> +  Logo DXE Driver, install Edk2 Platform Logo protocol.
> +
> +  Copyright (c) 2016 - 2020, Intel Corporation. All rights
> + reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include <Uefi.h>
> +#include <Protocol/GraphicsOutput.h>
> +#include <Protocol/HiiDatabase.h>
> +#include <Protocol/HiiImageEx.h>
> +#include <Protocol/HiiPackageList.h>
> +#include <Protocol/PlatformLogo.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/BootLogoLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/PcdLib.h>
> +
> +#include "Logo.h"
> +
> +EFI_HII_IMAGE_EX_PROTOCOL  *mHiiImageEx;
> +EFI_HII_HANDLE             mHiiHandle;
> +LOGO_ENTRY                 mLogos[] = {
> +  {
> +    IMAGE_TOKEN (IMG_LOGO),
> +    EdkiiPlatformLogoDisplayAttributeCenter,
> +    0,
> +    0
> +  }
> +};
> +
> +/**
> +  Load a platform logo image and return its data and attributes.
> +
> +  @param[in]      This              The pointer to this protocol instance.
> +  @param[in, out] Instance          The visible image instance is found.
> +  @param[out]     Image             Points to the image.
> +  @param[out]     Attribute         The display attributes of the image returned.
> +  @param[out]     OffsetX           The X offset of the image regarding the
> Attribute.
> +  @param[out]     OffsetY           The Y offset of the image regarding the
> Attribute.
> +
> +  @retval EFI_SUCCESS            The image was fetched successfully.
> +  @retval EFI_NOT_FOUND          The specified image could not be found.
> +  @retval EFI_INVALID_PARAMETER  One of the given input parameters
> + are
> incorrect
> +**/
> +EFI_STATUS
> +EFIAPI
> +GetImage (
> +  IN     EDKII_PLATFORM_LOGO_PROTOCOL        *This,
> +  IN OUT UINT32                              *Instance,
> +  OUT EFI_IMAGE_INPUT                        *Image,
> +  OUT EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE  *Attribute,
> +  OUT INTN                                   *OffsetX,
> +  OUT INTN                                   *OffsetY
> +  )
> +{
> +  UINT32  Current;
> +
> +  if ((Instance == NULL) || (Image == NULL) ||
> +      (Attribute == NULL) || (OffsetX == NULL) || (OffsetY == NULL))
> + {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Current = *Instance;
> +  if (Current >= ARRAY_SIZE (mLogos)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  (*Instance)++; // Advance to next logo.
> +  *Attribute = mLogos[Current].Attribute;
> +  *OffsetX   = mLogos[Current].OffsetX;
> +  *OffsetY   = mLogos[Current].OffsetY;
> +  return mHiiImageEx->GetImageEx (mHiiImageEx, mHiiHandle,
> mLogos[Current].ImageId, Image);
> +}
> +
> +EDKII_PLATFORM_LOGO_PROTOCOL  mPlatformLogo = {
> +  GetImage
> +};
> +
> +// AMD_EDKII_OVERRIDE START
> +
> +/**
> +  After console ready before boot option event callback
> +
> +  @param[in] Event      The Event this notify function registered to.
> +  @param[in] Context    Pointer to the context data registered to the Event.
> +**/
> +VOID
> +EFIAPI
> +LogoDxeDisplayEventCallback (
> +  IN EFI_EVENT  Event,
> +  IN VOID       *Context
> +  )
> +{
> +  DEBUG ((DEBUG_INFO, "AMD logo is displaying.\n"));
> +
> +  BootLogoEnableLogo ();
> +  gBS->CloseEvent (Event);
> +}
> +
> +/**
> +  Entrypoint of this module.
> +
> +  This function is the entrypoint of this module. It installs the
> + Edkii  Platform Logo protocol.
> +
> +  @param  ImageHandle       The firmware allocated handle for the EFI image.
> +  @param  SystemTable       A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS       The entry point is executed successfully.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitializeLogo (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                   Status;
> +  EFI_HII_PACKAGE_LIST_HEADER  *PackageList;
> +  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;
> +  EFI_HANDLE                   Handle;
> +  EFI_EVENT                    AfterConsoleReadyBeforeBootOptionEvent;
> +
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiDatabaseProtocolGuid,
> +                  NULL,
> +                  (VOID **)&HiiDatabase
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->LocateProtocol (
> +                  &gEfiHiiImageExProtocolGuid,
> +                  NULL,
> +                  (VOID **)&mHiiImageEx
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  //
> +  // Retrieve HII package list from ImageHandle  //  Status =
> + gBS->OpenProtocol (
> +                  ImageHandle,
> +                  &gEfiHiiPackageListProtocolGuid,
> +                  (VOID **)&PackageList,
> +                  ImageHandle,
> +                  NULL,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "HII Image Package with logo not found in
> PE/COFF resource section\n"));
> +    return Status;
> +  }
> +
> +  //
> +  // Publish HII package list to HII Database.
> +  //
> +  Status = HiiDatabase->NewPackageList (
> +                          HiiDatabase,
> +                          PackageList,
> +                          NULL,
> +                          &mHiiHandle
> +                          );
> +  if (!EFI_ERROR (Status)) {
> +    Handle = NULL;
> +    Status = gBS->InstallMultipleProtocolInterfaces (
> +                    &Handle,
> +                    &gEdkiiPlatformLogoProtocolGuid,
> +                    &mPlatformLogo,
> +                    NULL
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      DEBUG ((DEBUG_ERROR, "Install protocol failed.\n"));
> +      return Status;
> +    }
> +  }
> +
> +  //
> +  // Create AfterConsoleReadyBeforeBootOption event callback
> +  //
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  LogoDxeDisplayEventCallback,
> +                  NULL,
> +                  (EFI_GUID *)PcdGetPtr (PcdAmdDisplayLogoEventGuid),
> +                  &AfterConsoleReadyBeforeBootOptionEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +  return Status;
> +}
> diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
> b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..137f4dcebe4ebd77d5
> 0f35ed3b31bf76c0f5f55d
> GIT binary patch
> literal 964114
> zcmeI*zjE`um)LP-
> CmE~SVz0nu`pl&EZ0BMdw`zPTz7I7nJn7S<c9AM=+F#*I*h((8
> z@E(#P2?7V_fFLD{^4IUnM<gW@;0M4V_(#;g{@cI&pMTypfB*Bp?sorOUjN5`
> +wK1U
> zKkat^Ww&qV|KorE^X~u3N19>!_qN-
> ~|GT%h?nVBU(cS0g=kD_#pSyqmfB$Q@dwi1N
> zRR($E@m+>b8NPPAr=1LsGRVl&s|;^4yvy(@!`E*2x|88ih9?<h;`L32cNsoq_&T
> Ti
> zD6da4yvpz<!@CThGJNfJGP-
> +zl;KH+R~g=9c$eW*hA+wFPKHMro@98H;Z25j89rtB
> z+U?~3-PfZGPcpp9@Fv5%44*Q5?Vfg$&E2C6&3~^lyvgt`!>0^i-
> KIT0%IlL1uQI&J
> z@Girr3}4-5KRwFplMJsiyvgt`!>0^i9m(sXygteBD#M!$?=pPK@YQj>J<98o46ic0
> z$?z`2rwm^m<@=+&KFRPZ!<!86GJMML)iHlQ%IlL1uQI&J@Girr3}0;#JbgXN>yr
> $x
> zGQ7#~F2kn`U%NNi{<qzu49%9m%Fz7xF2kn`U%R)*oeYmMJjw7X!<!86GJM
> ML)fL;*
> zqr5)J@G8Tb4DT|0%J9_{>FcAsKFRPZ!<!86GJMML)fKlS^7i&5!>bH$GQ7+1DZ
> ^J+
> z72Y4^^+|?T8Qx@gm*G=}udbSWKFaHp46ic0$?z`2rwm_h6?*%6l-
> DO2US)Wb;a!GL
> z8NPO(vi+aCM;V@Ec$MKzhIbj7|Gv7a_4p{SPcpp9@Fv5%44*Q5b=B_aQC^>
> 9c$MKz
> zhIbi0W%%l<<m;onKFRPZ!<!86GJMML)m7KGM|pjc;Z=q=8Qx|1l;NwZ%I}Zz`X
> s}v
> z3~w^L%kU|~S69tHALaE)hF2NhWO(2G`+xlGKIC(6vcBE!r~QBT^V5vUApbS9nt
> %91
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKw!SW4}S=h3CyotEP=os3Y0Y$K83)~9oBv}34!?n!~z5g1?E>SmO$VR1q
> #~>
> zA4A{{Yd@QWz<dEh0Rn{r^D7riAaI8Qh3$opA#jJapG`twzCaoZP7lZD`RiF_iI<O
> k
> znjhxeh`=gE%t{al1YQoa|9&etjk!+R<HO7N=Jm&(KTb)Gm~k5d*RKtvc;^Do6|M
> by
> z)u36kvZy(p*3D5xkslr^9HXsZ@)80Sg~=iam;yCzea#T{{B34We{<TnP9OTGt~vL
> G
> z<MU~u+{)B7D*<W!4S|}N`BM|;bk66Gn!Apt4e~)>^>ydIR6$NRgsJrfu3HO8?J
> o$_
> zHTBhk=Eu+Cn0cx>x?jI&Ij6aPz*}LB>lZX@{ObaBG4r%i(3Ft5IA-3!k$F>zo*!0d
> z;jCh9fxq6q+5Ytf>SE^4Izh7unM-
> 5l=~pkA2L(b$bM1Jy#`=N+VibW@1S(_Z&l(qA
> zj%}l;*o?3--
> Nf0<W*a!885YZ}j91hy7D2!isEwH`1kGcYwwXQs&9FhPbe2F*XwKYc
> zE}e(vawFq&O7Lbr`(pmBkxeUs!>t^-
> sT+E*vYvVGdEHAM)iLwuXW@y&bI4qJY<^T_
> ze_<vkG;btKPO|X}6=8Xj-zV#Dg#hqjt^a3w==Nd!EzZjE<6Bw1%=`ZSP*?t9<=l90
> z{~&8Tyr}D(TVM-f=CZ@{L!a{89Lwj!Rzb`RH5iWsDr(p7FJhnOS=d);HqX3Xc{)r4
> z_CNVhw75t5(5yR2pqcR#W#gQuLsY&qCfm)}KS<=9Y~TEeK61@S`}|Sass-
> _CtQPb0
> zOw62LTFaL>?f3f!`IG&%^a8$RY`?FsJzjoJl3bUXq$kNW3GSPwH1n^bcHO`t=4q
> a3
> zH?StRFDBxCx=M?DY4kCJx4QBLG4s69Qi&eEkLt>&8=jrAL`>P{O?_98O)Gd~44
> E98
> zyUf4+fs-8AG{-
> gJX(5@Azn8<ucN5B1%%KF!KDFtARFmAxi=;OzxuDK%XtcedB!{~E
> zPLc22s@wTdKh`STX$e&TTOD3Ctl8n-
> +^*owrjmWA>o3^`OC(4nGg=!o!><~a<TCn9
> zn41NC-Ds@~C)4wp-
> ?JZo(k&qUxT;Ro>1ZZ+G<z?hX)u0jj%C88(Z<Ryel=&@o5`2s
> z_ewoZNljK67DS(16EB;;Hsz1<^ul#*XWV`aL=@C!Z<f9G_&Xw2gqRf7?0m=qzZ
> 5f@
> z3SJ*JEs>z<<VNd)W*9Q>xSuI?duZ}=Mw-
> gk#)gBOB7Z3FS4nL*lG)9_u)nvDVY)mX
> z<VxoA^WkIZV@gi@?}Ob2+m5E}7TWX*!)8rGzJX<|Sn?AcJkQQ<caLALNyj&$S
> P{Z5
> zuY!zO+o|>g*Xd`Tx81LD>LyqsIn{9fetN=KO(UK;37PjDGp!(I#5ai!<GU}?k1GmD
> zO%GvQEE<!y=JhjA4^9X>7pvs8iDUBey`VCkzNh`mxXz5z(&IcFoAiz)>5a>6YRo=
> u
> zr$&?V?Xv>a&riH^t57!{GbNDKJb2d<31ees{PeSrjoq?)nU<OR`Sb%}W^VY{e91
> 9X
> z8}Yis(e{Y+rJx@dA5}$gvts7{drrAFaZJLPJbt;ZKFv!_!haX03!-#nu$f8IG42Y^
> z+p6GNLfDYb<H;2!D<|8JnKe<<5>Z5zS#zKF8=v=^SK#fZ!(7~H%p6sQe%!(9SFI
> N_
> zPx{SqW2VxvCY#dvtBIO(BW9a;6Q(6fdnRc{w=u`OOmkYa4d$wUlJ;aph<k{c5;e
> c)
> z9V}ZSVQ4bO=LOBEm$~@+=1CbZs!t0Rj`szNZ~71N(gmd5i+zZ`R?L*+<RI<x(dIg
> h
> zM9sNXYF_;bvLop|?+(+Wmbjh<AK%od-5H$M#-
> |%@Ujf=DVbChh<ipdX{3)yO)JnMO
> z`OKlR%&YO1$gs-
> HNWbiyO8?yM<@zO?75lKsC&K*viI~|4_yK99nE9}vMap?tiDF^#
> zhGnIVS9EEE`XIMIJ)2$4;IrErwW7(Q2iV$IfYS3xR$<;t%>4P8^Lt{Jh*rhbc@M>Q
> zUC5lQq@pT^%m0~}DNYh0tZvmRF>_fA>n=jg=xWwnLkw$7bI)l1E!?nL^yA@Y
> H#KhG
> zqFLPF(rq?_u~LPs2(cg=UB;};T(O_|BO6(MaAk?~_0E4S4Vp^Gq@S5qYimw&Ze
> uJR
> zrNW16D!K-=<hxzx#H1k^nH;m*jLpA-
> 7;aHNe#qYu(0^oeul6ByeNW+~i4WO7<?534
> z@w<tc4M_3fvL%w0P2VW{i6AXx5;JEu=X^X`A!aV^_VwG6&*Y@;)ZO0OCo;a
> ~lN&#?
> zwK4NjO>%X+c<ap7CN~<%YOM%yS245ryWp0{q<T9O$_^?mM)i0j{g^u^%uD
> ?q*G*>L
> z2QGOHXp)m`fLI<gi+8n?3~3YgS;lh#uF$DHr=2y?^0tk6=G6|TsPkKBcVD%;<*f*
> D
> zUoo@v`IeSQ7@FMif}W-tGU;dLD|qIe+%;9FA^FGV1!b7Yk}}&rsk!XISkok@-
> ;)??
> z>-
> 1Bbn#!MWkj+c4)s$_UeY3o_Rx3i>S<IA^nk9;s$XN4A#@yuekV(ueDW>UXGT~
> @x
> z%q%@CJ<UvZDwE5xF1a-(yK3c);n{-
> Y`kOK3lUtdUX)oRO)gGK%7hQhT3S>oyyNj98
> zvqSZ&Vu?&^pF5@Pq=H0qRUr6C>1dc0^Vqz(#d@v3{mDLZz1p$)ZkLHhYLy>N
> -F_x9
> zbHuuVG4n9G^5I720l(hMvLeJC#ms&)3wB2RN5e2wJ8lNe?zS)`xr*8uX3&b6*
> |S{X
> z3TBL(2a{KfnLGVN{=%4P?-DAC$-Hq=u2U{<ag#jhJCeyqHa21Q3C+fq-
> OyaerE3K0
> z-
> 91W^9h%JI60|l^&5a%Ohm0*4@sEBik=Y3w<(R*dHe0^=H^Ph^@*m5DmT>9
> 0<7zo}
> zIk;xb)Vqw!V&*!x{e-2FiiF&2T{9n2R73Re?gmH9bC25P8h;zj=B{_KtVQlIX6n7|
> zkk%3jYk1jsHfS2R9f!Fo91k;N^fUFy5-
> vP@+}H`F5hANmxS7VsRL?~*bN!Gh_qSW!
> z2!qntaN{jCHRJO)|CV`huH6>oZjl*<fAsE$6(R02W|~Kn4Y4IMJECMS=VeaNw+
> Xlf
> zoqiz9m=!Zu-Z)9tXy|E^y<p5#cLz&i=6bjNgvFJ+nk|x*C*;Dl$KzTpi$AleY5f$;
> zx%L}XF}so0J}mcGPOA~!R?Ivd(?9uzHu+hUd5_!jj({wYFf<j8>oHoZ%)<(^1)P6l
> zSXM@in7K3W)(BTpJZ@CftHw<AGSHHkX>3@&9Q=3G{&1^Zx<ir2lQd8MXp-
> vwH4;@~
> zjPdE)f6F|1=aja#b>{kVw=Y={;<jR@er}<GXn%yIJQ}1ADw$|nBE^v;_@LHb$=y
> %b
> zEjGzc*+h_@TuI3O=~o59h3Af+jL>r3n5lI%omQkR(gR%L$h<8}C5*Lc7F__62XZ
> z)
> z)Fyw;Zv+|VlF!vfsc2;t>Q+Bx_6wVzn49_67q|ABt36hP*h<W7%2)QiAEjZ_Xy&
> pe
> zOGJ}(=cPf@I6!OGR#9KwOkC^(2Ih5RrgnWRSL@HhM$AkLt)f)aMU*hs7EVDo
> ^EvwY
> zih>7rr4d@q)MjSpE_1KmYNbqaRohByOEI%4^s;CB3x;*{x^m2HeB-
> kLPRJx?*0o^e
> zd`ErE%(a)gtWB2EJNy3GOu4nT4X)uo?lYIt2tCQm<|gc`Kq1ZI@ob6QQ_Pg8={
> ~u;
> zl{A}@B{HuZ+BLO7b8-;nh0MPjGhgKVbo6&@&fQ7NF4%u7&B-iiS!o)C&L!-
> ezZpY~
> zoEJJaS(bdZ*(}JX{?mePkj~s%>mAZ32eV_|H#wGU&%8D{<I~xbfmVblDSy-
> 5+P+B`
> z>DOYNlFe>Hzi|8de6$kn#jFZyiS*0QeGN~JW$J#g%E<<mO$19{dDNhseQd7X_
> |crZ
> zEBxi<wB)N}X2F576pS3$4A&neo9%B>7Bm{AL!2CoB*mVsHqKY#liPrkHE(N%
> R!1&V
> z<@FnlM9Yd01;uZBr<Hizx(mfjsmS`V&zN#Erl#I)j3qK%$&9J-
> iDKEhKd#M2Ro@*K
> zzV_IqV`jHK1!wN$3zW&W*T&4EZl?0fJMznvYVkxfm3HBE7maFTlz^n09Gpja+
> 1zCI
> z*dQtWWi#@1z={ytjG6M3YN?afc8R6YX?2!t3*t2M>fFOa-
> y2B#UTMizRO56d*P3Ir
> z*mPT+?wi$z(C^urP$gX|{Sgb}GTCEuC!ft4w6lw1UKHGwj;51hN;#Hqe7bzxzIH
> 4Q
> z(9zqQn@snNBgL9y`4X`r#8zWw$wRU8{Q*nlTqe>mX8)b*rWF?Y60fMn{i4@
> @y;jWh
> zk6w3aD5~sd=DQd}(d7Gm`+Q>?mX70?yK!cqFp5A@jIW#znb_!va@zV5wce;Y
> R)pAW
> z%q$3+`HrR~(icuav&huQv@g`Jb9~J#YRw)OzV?{WVAIZ#<7V$rvez+tnB*|Dwx
> 8)_
> zQ_?ejJEG({t;y*lqlGqGmu^{D%r?w1s?fdGW?z#XPH3^(xKXbo&`FZpjhXiMdfSc
> 6
> zp3$^KdLF+~<!YqaVK}cox2!S0&)D@}jk>jR%(PCZv@~gCaY9k%*xZgmO;Tx(HiY
> +2
> zBP0pucj4`p#eKyvH5tzzG|AGjO1r`>|5MWKh=3|4v+>~`uK{({!M&j;+tx1|GfN7
> *
> zqC!_xij@}0I?5@(q(|WFYwUie`-SZEsI4w$IswcJnF8x<XL`VFFA#^lxaiEK<M>=r
> zyKZcek`@{h&7HRDfR+A+`<dzPHAc%eCrhMXiCIa_8b-`Cc!-%g4l#4$;`F-
> vM!M+r
> zI7x9jVMT~d$4uqUlPO{@?pY%J8gk1{ZM7+4rlxY9=fuqHm)XvX$2}^!ifvcnbb+
> >j
> zt@hF+mG+<edeOhSNB8l;y?J!)R%JWGQE&f@wc!`*F7Cbr7QUV=9xFoF70z1g
> `Ms#L
> zCflK&FR(PM-
> m;n(XLpo)M5!gxZvip0m$2ek8e1GUFJ?MbV5MVoC(xz`)`P`3Vw|yP
> z>uMCOofvDiBS~}K(rR1T)=bA^EQabav;3?GvGJIhHlZn@8nx{+y!{HCwr|wH8|-
> JE
> z9=^-
> |)T(OKuGM3va}Q8@2<wEuC~}=k*NM!|1)%dv?5<xNckO)Y+3f40+nbL14o2n
> N
> z%3CEDQb(SOF}pnKW2QX0^1HuNJA<t@vhyaW5o^_crgun_Y3-
> Is&wp1jGvkn!X&RHn
> z!&rLtm}yt#<O;DHP4r;og*&TO_Z7sw#y{P6+B*Z)eMrgtf<{w__ZKt0-cVpuH)`)T
> ztq5WEGrL%CuiUC#SBRO;6LvEP=axuc0(TWNi#JBCs@IH}c4*n9dt4{Tsxi|!(p4gJ
> zUn|1bd288!91rb-gw-ZDjjv%U?YNgz)GJH(h1;9+;C;_8L7F#14Ne1-
> 6(Q6DJTKXw
> z#5S7DPJe*QIrnO|(po=ms~w()4GKq`%BF9hCDP}nILw5(X~&%`wFx8(`7`>A)w
> ~vO
> zjN0EZD!}UfOs5J&!9gr)Vy2Tw+-=K=8!l~eCjE)#VI=##d?{BB-{d(-K@5#LigAiw
> zO3~teWxD-O9AblYr!&2&-
> o=U#dQ54T9GZ`L|87z*f=#<d%yc@M`azf_(&xW8%=FB|
> zD=~ARNJqS;;6#TgI7ngD#7rj<wQt(ji{RDi6Z@fejG^{ZDV+0T_jqi+a~gI~3{|5}
> z^R^;HK4u0L$2v0j^_ZFVJVHagbyy<((hh1G4Td?_ikYX9&FD6#cw>egWzW#O>
> WJ<3
> zuHMhocXESmTHR`5ro-XI^}*&a<Vzi~tLCs4cf@-
> jQgXDX=4NX%*V0pYomx}*EV!_C
> z8bLGsSe(17^fT2na6?Y?E_g|>aoUwp1Fsb`hmCYc%p--
> #mi%_ibi#v@J*V~uyZ(X6
> zc}kGqKkV1!)RE%Y+pkZ3t#}~Fq)4|qp_KLLQ}EO=vymI!fY!@eINQ&h{?>fHD*t-
> S
> zG|#AJo}y`q^yT8T2csrlFJ{UuMA0+P^~qzlnB&b*E2>e!R_<qdKhdM~J!)d6!(r9
> w
> zzIwE;222C1Vop}zPwc<dp2xJ@;vK{E-
> K|bp#juxO<#hhcM(&|n3+HN2{8W}~?XWgX
> z&DhG<faFn{X2nwvpVG5p={jydW<Gr6O0T|^sLecE_}cen95=J?<@JZt2winP(>
> V_r
> zN1(KB^mA5QQNP0I_4H7-w~I@yzWi@#NvmNSN51Dx=&xW$q}`-
> <5wPaiym=1RG}Pvr
> z!tcjS``}#7_j5teR2M9&QdU{_C0Mkg>4*A7yVujt1tMmqYjmxc>4i+S<5tnnbXr
> Ut
> zfu```l-F{t#u2VZ9WVX452+<__j_7#wmM}tY@<$g+iTjZJ*m)X8vLf^qxV#jr>&lT
> zaz{;8)~?gfv=7ep_MvrHrZE0<YeM45_;q5YbFpNSqsfGMNE07lv?xaXOd*|pO}?
> Lb
> zdQj_2n0IYgR}nLvES8ktxw1HIPs?vq&Gbn*>2lDUX2>y&$LS1jY<nc$tkBB*wzz
> Dz
> z8F2Nh93j^1n3*;N$!%tzdIK>t-phuxKN+56uP|AtnQ$6b2po-
> <w7F=JlF4ZfYqKZ6
> zpKbi<m*OuTGv%(u?+-U(>fdOrh?&mr#%ik5LhveySu>+m4U-
> ZtkG@4%W0I2z;hP&C
> zw@%~P4-`$i-
> UDwl;y0ezF;lNJdN<$(VrIVUB0RbMksCC9*IaG9M$FW^&$%20^WBGz
> zPAXS7v1ZInf2;R+kbApJI#uefyypJQ^?HYfOk+MfX14o|5{sZjl@ltHcQ-s?+_idg
> z=#53aD${_?jhVTUR`0C6ftYD_!?Qm>=>^T3j+vQGe?jxGW2RnJjOv-
> jF~^OVsqB=7
> zS;Wjq70yMX#w*tu>Q-
> QOQH}cCC$BezuAG#8TK<BQ)*NmiW|}*NY|Px*(W9XM-uuR{
> zSLkQv@BNB16Hhx^J+$6%#HeGlV`iM68PodV&-`O^Z---5>5xUn4Vh-
> cN@~Km#^$1r
> z(jI-G1jb)v8=o+HL*^Nlgk)sSon@Sm%!`>;qf)YIRWS9ejI{@-JmR$SV4U}`ua9aw
> zhzV<UqNJr{7tX&Cl)Bee^DFW86k#I6xDgrV#!Te`l#$uVTSvVf|7y&1D(qn(^hRc
> 0
> z^qIh<^?363mM5&1ZP}Z_)>^Q~((77RiphR0Z3IDaD_@|nw(43j)7q*0C~>}rX?
> oOI
> zoSTlB^_jDFi9tzEMpulPJ^lRG+~H3}%uFi%G&fe2p18P=Xe*7G`&n1Xr@2kOY%
> W=h
> zKe5?q3(zWf>!99>2m@3$EQoGWea!gtvrodHRl$-
> EH(9zsKhqSl!b_&>(l!ihxq((4
> zxk5kF*b%5%8fR`bX68bscS1k8rYyV3q|%Q(GNvpMMapr~xv4$v0gj6fV{%At
> XK0eU
> zbV5la{m@qDSeJ5)7HTbKp9noe&54<2_>p2xPNdy@%rrVla>6NZW0Z(f0g0Io
> P{rHo
> zeWPvInI8e2KzH4kS@hjV6HMvln4jO&n^ru^A7fknva$;m`M8kuGmRK>-
> Y>=>=oVt8
> z)q{6V{pB~9m^t)>;xZ3fU3w~~-Yr;dH2R{%g+6!d$4sle^r@a-oy3(c;B*E1WnIjM
> zN$Y?|d>fuLqn~;l+ia{+UA&`=vz1i`rbh*C8B2*rZQ>SUrU`2__{JyOfr+;BY+3R`
> zKeI%s{4>uV=AqWK3dgHedW}v$v!oI9k#AYdTp?oWKad$CY<Sv=FS#aaUIB9A!
> I`Q!
> zW;XT9`fyiM4wDkFwn^O&SOG5I+n%HuPgtvT`kDFrj&lVPC!S6dGgFiLId;UXIXij
> 1
> zm}xfNQ^^yHJU9Kx3Eom0df#eHneX`7w|J>RDFLy<;AAIl#lL>fDwTASs<q7IgMG
> HF
> z0QVa)Q@*UB0ueKZA~$x;7d|$Be)+H}Sd&Ait9Rjkrdq}Os&0PiS^rwyuxQzc9y
> 0Ie
> zy1Dbc@oD#MAhW7WVTe&f!nr|&Wp14X7}}4FO!m`O{=$_H8+3CqGxH5MV
> &+ihzZ5f{
> zU%nr#y4&S%e#~^1Sn=3A-
> _Ja$U#c4#N#RH)WZqNEG|x@y71J!h!e(vNyP%(GU7{MA
> zPdgIE>N|*;da)GZDz)1>oaiBy#k^VlqRs1F-)kiIy^DqPFs+I^XgCp2>1R$4loIxQ
> zpc~R0Mkd{dWKHU`>)K`a^#vHDl6LaX84EtM`BAHnrI)?c_tTe1k*umWb_KQTZ$
> sUP
> zMuPZ$4>3~>n#9bZ(1YTRYggKA>)nQRKffI0G2AcHp9&aq6OA~n;3i{cdYkjG?K
> 4L5
> zPfVDxlH32NbpcR2I5+osMpd3jSTS?xXPO<_sG5cs&u<}S9+Lb8Gm4ayT~mGA|
> 5N?U
> zq(;}f1(o)>{Uz|CuIBnNGufn|HbtZ15m%7?el*jl)(M%%d_Md1@8Z=u{?!`yQN
> KRX
> zmYj2lF?yB6%(lN^eQ;V?#xGIcLd-OSR8bpNP7D<-
> HzEgPW_Hew!N*HS!xE@Jv|IUm
> zKxtH{cbh_VVbi?LsA~qpZhyM`d1`(?(|(3^SPJfUCsUnf@v-
> r!IWC)N_QK0nv5`+b
> zPst}!+78o-NX|ZP6tO~Ke{60gG|A<8V%Sw$3-
> &7?vm#^G`HA99nyfK%5$BxKvNoIs
> z&9ddD8R@3}Qp`+mZ>@KWEt{yhd-
> jgdwPq8nNr{=pV_Vt<ttuV01*gIuqK~(eYlO__
> z)ICfp*#0{hwaO#yJXrC?EBO)2ikat~v|R*YarEQ;mnf|bx>n3oj;#A^{**E$C+6zg
> z{vV2&iCTEtW~_mAW5mp?+n<V=>YnG^z|)<U6%2AWbf(UJ%*=m-
> aEv|UShv3Osf1gI
> znN}Y1&(DmY;^u#^G1J771IMwPhcWG}QKzR=(0aG1K$^+s3VQQ<e#T!#KQrx|
> Op;bM
> zDwlp<rd^}f+T9<Do8(2Ecs@9Vs4lhLnMMUjPEeXxfXeHp)(rYe&~^p&(=Po-
> a<5$m
> ztkSzyKhrQxzEPjAIZ@Co_l;M1)BQ}jhbRB{{r#W?&1_`Q_O<nHv12<eLDN13TM
> ;vz
> zELs;GqQ;Pw>9$2%Q-
> 6S_Zf(iTXa6RwlGSYJGuBQlE=#NNIaMVTv0`R(Y_6U1iRy+n
> z+5Hmb4a7`y*D}Lt>JS%3C~A*e#nwaGYf#_q7j0gho|3wJ(M)ysnTrhS8J#+}^Eo
> 0t
> zkNKNwgu*G{X`yz8x$QZpUQ&MDio9}A8hg?)(l<Ff_r<>|c1O?8>=>+5l<~p26_
> 1>9
> z56!KZ*>nZ1WX^R%eQB=)SqopOpJ|cies?nT8OA4Vv##wo>ndq;Lz?9yVHsR3
> W~%!i
> zy{@H~&DtC~Zik2H@B91X=>4RF)zhqqnQ=Rd%0S(3g!;p{7XX#U;qXLRi6)<q-
> W9Pf
> zYtdqxpHv)&GMEM#tL(he3Ynaksq74g3|S+mpXMvG<(qTPk`>{c${cP~Fs>Z|4H
> =)c
> z$}niwSMJ}And$FG1X#|f8Z#f{4)f^m<@lXBBjUInhLQ<J+{f-
> 3U%04<na;O&w61B8
> z*<jRLQQA11C9KkUIX+~_gB*3E)@ru+p4FnJJ9I0U%?Slo%zU<Q)JaNXIz!IQq}5
> {l
> z$aEKQF0A!qrj>>G(REIZ39dIdZQodtRl+@vv3TySe$nRD>Srn(<+r!w_S04!3Nz+j
> zH&<h(tiky<p?VsiO}HXvdL0f$aJr5Cl+y~89niFe=ZZR=UvztapRK$4zIkJzKn~kF
> zy%uimRjfu6i(B>m+1P^**~*W6-$Kl^wy*S7quy-
> f*lNsFdr8F`lZ%=8DiFWpB$bPq
> zKlb(H=mK4kXhqEQDusFA5+v>IkW<X^omXEW<yHFhWnaA?vKB0SAEQ?H@e
> pjH)m@ne
> z*I*%S)QBmkpkp<NmyL95JzD$Z>-
> 00Tt+3e+r$wb)L(p{Ee!Ao^$11qqcKC4lNWW<F
> zYV0z%8Z)D348|_UTrGA=xP~K*b)o$@?nS_~X3o86{yaZkHrb2uHa~40oQ7R
> @D;mve
> z(7D>y=vwbJ?|XkIYX#SdnbtnY`Q>=6F7=Ib7V%_7#LNlDbRvx-Llv`+baTz2CT51s
> zY?{4pDwo!f)o#Q)IhpoX=Txf7c-
> dr4+oo;LGmg1~3SfoS;9~_8R#=N_K|FbKANd+D
> z5l&wxW}2JlwGM^veCljY^`5SUm^t;BOc^oLKFyd0psuPpZ9(m4+R-
> `x?EbKF%eYrX
> zlF;jQOb4k2@v_O|u%5da$(4Sywd29L^{IK0zzix)qWWL6*hl^mfcip{xmSsq5}}L
> @
> zG!A03^{ES*UW3Rk{>%3osX?N6V@eN8C*?euaFQ}&ru{P{xt!I+OglQ;*Br);_1
> 2Q+
> z*ju8lQw!r|lfQi3-0C~lRiJSXXas`d?*n#1)|$o|pp7-L*{bB)GQqs7#LQ%89%Nwt
> z>C9HF-Ca3t->7^N#oa$+@!VVCI*na{8Z-Cl-
> 9pjLL*3+}yC}L0I&M~V8Y{nMkSXYz
> znCbQq&GS8dL3llvv>tc|^AfG+T_EqX61{4C8=sdc{bs|58c<)i5}fLo+0|jI!yA=V
> zG<l7fX`RB5J6IBoq8ZI5J8j=sPuf-
> @7nw8`&%G6{WNyq1m%Z?~<5pj<Gxcz2F}j<&
> z3;D65v-
> fq)PH=d%m!7cpi?Lp^yW`9Y<e9R}<!Hn6t$Nc}xhAgWf}PP~G?m<HGT_7P
> zey>=x(;b!yMy?Svjs1`0q}S9~ta;KtYZv|P?*ZvSA}Ey$k2-Ev-R~=$UNY&SZo4H_
> zG1EOr?ym&qvAVAg>sf8*Dh1)h%<wA}lY~$EQ}Z{OXH6Kn+U#4#)}L9e<M-
> 3d?KV=g
> z;KzDp$EEx_t`IY&30j+{=AeY{o0yp|SM!|(G1CqyYsO5!blr}EcVw<z39y&Re?#;^
> ze(B@o<#0I4<5lE2Di05PJBXIl@U4BuDv++3XAVT#+UnHG1j7m{+3J4^E=MVQ
> %<OXE
> z8*0R|4yNr!lWbW3c#-
> S|&R*Y`#P?j~anWOFkQpC8T|5@9$vD!eEv#_$OU4~HtDk8X
> z7cuis$4o13bal?SAL++@28_}KvmwQ78e!efR9AC(dGqoy)7tq+2EuJnV60i~Zy#
> D8
> z$iGL-%-fik6z!OqIrOSJHg`{G?y|?p=SuJYJh{^CG5eYMuR2LR9<JCmwC#j+JYTvX
> znznDlf4grPN4xE13u|v|!fPa{sTb_z{b?#ze)223c+7ON<uoVFYK?isOheHsvT2=*
> zSCZ*KJB6HEO0An=l6KJaL#CFnxq<m=)0`z6f@X7+{u0~<p`8N=x8rWcm3`0<dY
> aO-
> z`cH?s3N<k^{*srK;UVYoh*~eLKDOP_NVYqF0;tQ0Sw)kztu`ZH`A49N#Kwi^e|Iu
> m
> z_QK;%-`<Fs-W}h1N24xg794^Y{l1@X|5#6JF=qYFw|V8-
> *cd{!o_j^@y8T5m#~E#P
> zmX>b4ZMv&lUJ*0XQp%TTz71YDW?GfH&6JwHO0?=sVy3}q#LRd<9j|58nCXP
> tChhFc
> zx19<?rdm18wySSmQ<3d`zY?5dx%-
> $lLXcb*R~UxKWSsub(9DmS<0bQPmH8qavKEi1
> zF>AGcrdlh*ESNQP+_2Thh?xdyK4yB|%*-RSoZzP&BDa;q=?}M?aL{g-
> JbkP6I@)G+
> zJJYU6uvE5zX{|9>P6;K!yLU8dMUKNRe+B5|R1uA6cFa_7J$u>DUXNP0tSz4t<
> =l{|
> zUxLzrR-Q-9G(go@(gZR4S#Zr7^`PQ3h-}O><5#-
> @avAVBxygM0P<C!i&8(SMCH8ea
> z06V&C8)*1%`K^3d{Q0&nQ``M?Rb+Oo(+kPURadz2zn6@e_9^-
> %CvyU@>Q+0Gm}$u6
> zV&;Q;{G<g3DP}Vc$pLn@q3N|e%(`4|ksBjF<aWsRmh#j7;rrm9$ZXe;X)IQ}9iB
> oM
> zH6tguYbk{raYy6E;rB`1M|F};KV1cy88fqIYx2*^j!L<oykN{UpWE4{Un3Rr$yxT`
> z>g0IN-
> 5)cGwwK|%lY>Mv;{LWpQ!rX^XqL63SUzStv8b&Jayw6Zjk<l6>JU~CYdm)l
> zWcGOUX77DPQ>$%O);9cJrUp!^k}^@#d72qB^QYpoM-
> NIyn^_l&na>5`+pL~`#d&VN
> zZZZE)mdgE5&IHNNK=O%jd81R74-(-DE;sIU-(F%<`3<#$T2W$vOpB?Gna-
> t^bMnvf
> z^_%mpJ#mJNX)Ta7<Yt^!51sZ_*R;uj7HN%~ZTc;3Tm72s32G$sVy3lUn;A6Krm
> *~c
> zrkrH*p`50qIfe5wKdR`bTlk4Et-|qe&DV{Yr|;}vdXdD5nS~pxd@K`(oPsuXA?`(|
> zb0)eY3nfR{S=pQ5?1P_lG5>m#x+lqIY~yc~ob?KuNjqNkoSs=R)2v9jLyjb$-
> HeOG
> z%;$ssd!@3q%?2-
> Px|a@_+d4Kky6kC<u;G(48|AGyv!kq!nLqg>s`6Z^pUn3yY@L^B
> z)js(rdG%Xt)J)yO%vquA9F=VHj7o7rO}MdBQ1@z?h<TA?^YlWdo_ftWjDRm+>
> GkAh
> z&kfQl9SzgCZa;Iym|429>F07)Z$Zo~J33FZ;>|H0iew&~%a?t|D^B}|5ASE+B_H
> WN
> ztEnbl1~>bDMZ0wBM~0#}W{S4aJleGz)gf%t-
> T2D=Ou39%bgobmw~v7`PUGx~qDi;j
> zoHM3XJQl9cj+t``JY1_X-
> mc216lt5ace=$}n|v^HXkLE}NVZnJsV+%*?u_&hJAgHL
> z+6(pVGmJ{FH|a;Kb920z&s!(<0_1SisJzBz&uBt^_bgX+!)*5BtHn$?qI)@fr0351
> zgpyYyrWjEDTXVKCNxE!CpVW-kaK+a43Db-c57(L-
> H&VM=%uEwH=ho>*80Rx(1?HKk
> z8D$fGRK1il&^jH>;fhnZ#{76jCBMMd-
> ^rYy8F<qXH3+#3<t@lA&@Q1FeK0k<)~@1o
> zjQ`|;f$bv$=iN|Ww{PhouMje8j-JBmU_`N^pCby_<%~-
> NHg2&=8?D)q>WSyS>K!V{
> zyOldh#*Udk))mkBnQWFwMW(=>PkY9<H0exLEnR$jpUZ6UlsKI7dx0uKam*|`
> qAd^g
> zvtwqsvAJ>C8gGLtoz8f(izSy+Yra}g_RMf~R?K|<$lk^suA+F{e1uOLA-tGiZ)EP>
> zG@U;G%VOs0*MZ!thh>c{=P;e0Q<;A1o~EoPar8A}@@lmd1I7z6LmCHTCF5Jp
> o_knZ
> z#WkQ{*#)B|z2$Lp;<2lQ%uDt&WrNzsg{}0D(aDsQ(pF2%w5u*LGj4ISre_@HH
> sw%t
> zqmg8&G-
> j68_S_ZBq^?|~pP8f*&sbI|uM;va95ZLt!bKmxR?N&7%ff!<+8s^5O|N)|
> zQ!cSZMS9x{=e~OzM}hNnX-tbZx*%pYA1OZxSeoxE#>{aWmxaviX|qh3)Xt8}s9-
> uw
> zs`7}VAeEUPxl+tDcGF8^=8t*qVJ=55iiL$&-
> q4)Xvp2Cg%WeAYStp*H%8`c{<4IU@
> z@%WsRfcd@tWUW_>nM1k@LuQ%PkXrRfzO=IMglYY;m}y;#cA7=OnI!k?iP<8
> F-*8W6
> zc4b)G`H7Ot??|E#-
> qmDb?CGSdcTXj8VCFOCN_MBeaz1m}b<pgNJB(MWj8|0SFx|fu
> zGt<s&V6i-
> Au6CQI721OwdtV$WtQ&?(;Tksiu~}Dv)LvW3W*5cGnQJe)c&@I~y4NVI
> zSo6lu+qmpF>(H#FL~CB&v`?3mTlAT5HGe8*+P$|GVx|N!`$|_-
> 5}C<E@nNI$ZM)3+
> zr?ag9J^kdJO%;WnuCdHHcAhGgM1jL}5qGNKkmncrnFYT&U~F0bSSJiu>x>)O$
> h{RN
> z{Fh>;9Woc*pV^}>+u1fnmi;A+K8eZevYIN%nO`=_RiV3>KjV@^eKRSDne)%Elm
> wV7
> z_cIsv7D~2gQty{cRMg%ux%$dbk+8K$dVn~;Dp~87;NbKt*63#nZBu!cbT$u8H
> p9|u
> z#uo<ZquHmmMK}I#`N6qUH7o}|X4af4EeQ8ljG0mk_sar_x#Ny&{Nib=yfW{FX
> )fE;
> zOae8tFCH`P;2<VW!zel+YH6Dvttfx0@DwY0AW>LUx$(X1Txx@~_x#vt=I(8(>|%
> <z
> zFW7y%F|+QDG5-SAHDjj#q(QstTsLHLf2Lg;{ksLRXtkL6BUMQHniX-
> ZAeUO?Y`U5?
> z$?e=eZO?a~uccQ+mfS+)#mw4k&3(MjuK$WL^I_px{ItKM)$;Y`Rn+D%@xRf}b
> e@#j
> zfvguZrO*0sl#n?yj#WlX$$h(@pPAZDB4)P1^;M*zc5P{q!qXr%N6$TjLtOoA7d
> Osa
> zEoLt5WV$EK`pUT4YhN}qUc<EiK+G(CQtFy9Q;7E;YOT$c(@XNhlwmQs<EP>u
> Wjkk}
> zOeL4wJDKkv;kNK{uBH0ViJA3B{r&N5E&;XnmG-
> RN`Zjz(Dqgisx1byShqTrjsmO4c
> z^nJ(7=a=KR-
> <djltQ<3&&SuHOewzZ62L$J;epp!c_`W=BJ|7F8A6rqowzNpuRiN6h
> znzs^mxi0C!$_<Uy%C8bLXYZ=h+Tq;IV%Pb)chgL`bHapfIA(qy7W^IC2mj5AL?<
> UX
> ztAd84;rK}cnf;LTna^_#SDuVZYDYUYsT;B%c`&b)hpTn#(#AhfbZ}nZ7Ze?{*3{qj
> z*|^)i<jcp*rgB%Dw4YX)UkI6Zd<`gUyIUSV$uEe?FJi{Et9|<QxBTMyy4!X-
> b*Uw1
> zH=D<8A3vnqJtx6w{l34ck_TQm#~%)grCoddr%$rK4y4wgOUKOp!?&75pSiNv-
> w2t+
> zOtr$?-
> ptd!`E6nO+073bn$i7!R`i;;MW@qV(rbU@v+HnIrdL++H~c9pq@Br^96y`=
> z%q5rOJ94X=tOm4|&Sy3|=H*??W*f|~Kd;W0f4ZW+hAY3}WAiYZ+aD)pR@Bt
> XFJd3x
> zw$)AzKE*l9p9WdsH>9k4hShAZ5HnBf1x)Ys!lhb$ap8?0470N6T+O)3<zv^sdK
> NM;
> zt_v(L*Bf7hA4Ha&b2QFpuF>?2uN<l|v*cWaUK3=lL`&K8f2`BNZ0kkA9xI!h1#e
> W;
> z$uPBL2ObrP=N9R2od`3>_-_m3O6z{+%lTdVZ{d-c-p`a%0_(KA{Ff-
> znE7IFtMRU!
> zzWgY?4WzVo{8GqVdOma6&v%sK6nyS_PtW`9IJBko3kq)IACX@*w*MAx--
> Dc4PXFZi
> zcHw&a#Xr*Z%Nz-
> QYRudn?2XO5n_N)rQ(yG@TOo64%*@a(vZz}4S55|RDSZ7(UaN|d
> zg%BtZ_%LrTy<~MS$Xxu9Np{xS-^Gc{oNk{uI>{IlHy|*x6!|y;r2_f03Ky^UrCAI<
> zH_g)_c<0wfxdJpTlv|nlwF*JPcP{Xo=i(}8rw#HZj?TXe?vtBlo2hFERMajOLBJRI
> z&5*hDe5N$Kg%7RuecVrYPjS3PbRZ2)z%4pHfIx-
> 7@1BaQ$ndmr$T$6e`S5(+k2y?p
> z&(uW)Dry&tAm9lYx0PPBI-
> ghWWlwoO&DKNmZD?h&3(caFnU=@R%(+mRv)Vr`@XH}{
> zg=6!kfyyIFKAgw;T;%QJ8V^CcnFw=#8Tr#qn~lGW!0#TIOCzn=tov))Y|(`TDry&t
> zAYcnTU!?mrW2JWX)ORn`zF6)338?jlnF#zff%|LPY|(`T{#w&udl66tF4VqQ?fnU
> ;
> z^@o`V{5665Yuaqlg#`Xu(_niMPz5g3zF6)338?jlnF#zff%|LPY|(`T{#w&udl5hY
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> **
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> 0
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> {
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> IL
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> ~
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILC>Q
> uo
> DNG4Z*
>
> literal 0
> HcmV?d00001
>
> diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> new file mode 100644
> index 0000000000..b5eacfc5eb
> --- /dev/null
> +++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> @@ -0,0 +1,9 @@
> +// /** @file
> +// Platform Logo image definition file.
> +//
> +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
> +//
> +//
> +// **/
> +
> +#image IMG_LOGO S3Logo.bmp
> diff --git
> a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> new file mode 100644
> index 0000000000..25b46e4bff
> --- /dev/null
> +++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> @@ -0,0 +1,55 @@
> +## @file
> +#  The default logo bitmap picture shown on setup screen.
> +#
> +#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = S3LogoDxe
> +  FILE_GUID                      = A3193794-FCBC-E9A4-1AE0-DAEA9A499808
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +
> +  ENTRY_POINT                    = InitializeLogo
> +#
> +#  This flag specifies whether HII resource section is generated into PE image.
> +#
> +  UEFI_HII_RESOURCE_SECTION      = TRUE
> +
> +#
> +# The following information is for reference only and not required by
> +the build
> tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  S3Logo.bmp
> +  Logo.c
> +  S3Logo.idf
> +
> +[Packages]
> +  AmdPlatformPkg/AmdPlatformPkg.dec
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +[LibraryClasses]
> +  BootLogoLib
> +  DebugLib
> +  PcdLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +
> +[Protocols]
> +  gEfiHiiDatabaseProtocolGuid        ## CONSUMES
> +  gEfiHiiImageExProtocolGuid         ## CONSUMES
> +  gEfiHiiPackageListProtocolGuid     ## PRODUCES CONSUMES
> +  gEdkiiPlatformLogoProtocolGuid     ## PRODUCES
> +
> +[Pcd]
> +  gAmdPlatformPkgTokenSpaceGuid.PcdAmdDisplayLogoEventGuid
> +
> +[Depex]
> +  gEfiHiiDatabaseProtocolGuid AND
> +  gEfiHiiImageExProtocolGuid
> --
> 2.31.1




-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114680): https://edk2.groups.io/g/devel/message/114680
Mute This Topic: https://groups.io/mt/103975435/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [edk2-devel] [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
  2024-01-29 10:42     ` Zhai, MingXin (Duke) via groups.io
@ 2024-01-29 10:59       ` Chang, Abner via groups.io
  0 siblings, 0 replies; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-29 10:59 UTC (permalink / raw)
  To: Zhai, MingXin (Duke), devel@edk2.groups.io; +Cc: Yao, Ken, Fu, Igniculus

[AMD Official Use Only - General]

Also, I think we should take some time to remove the override files under Platform/AMD/VanGoghBoard/Override/edk2 although we have the override mechanism in AMD build tool.  Figure out the edk2 core solutions to get rid of overriding files.

Thanks
Abner

> -----Original Message-----
> From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> Sent: Monday, January 29, 2024 6:42 PM
> To: Chang, Abner <Abner.Chang@amd.com>; devel@edk2.groups.io
> Cc: Yao, Ken <Ken.Yao@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>
> Subject: RE: [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
>
> [AMD Official Use Only - General]
>
> Hi Abner,
>
> Got it , thank you!
>
>
> Thanks!
>
> -----Original Message-----
> From: Chang, Abner <Abner.Chang@amd.com>
> Sent: Monday, January 29, 2024 6:37 PM
> To: Zhai, MingXin (Duke) <duke.zhai@amd.com>; devel@edk2.groups.io
> Cc: Yao, Ken <Ken.Yao@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>
> Subject: RE: [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
>
> [AMD Official Use Only - General]
>
> Hi Duke,
> The entire series is merged.
>
> Thanks
> Abner
>
> > -----Original Message-----
> > From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> > Sent: Friday, January 26, 2024 9:11 PM
> > To: devel@edk2.groups.io
> > Cc: Zhai, MingXin (Duke) <duke.zhai@amd.com>; Yao, Ken
> > <Ken.Yao@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>; Chang, Abner
> > <Abner.Chang@amd.com>
> > Subject: [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
> >
> > From: Duke Zhai <Duke.Zhai@amd.com>
> >
> > BZ #:4640
> > In V2: Improve coding style
> >   1.Remove the leading underscore and use double underscore at
> > trailing in C header files.
> >   2.Remove old tianocore licenses and redundant license description.
> >   3.Improve coding style. For example: remove space between @param.
> >
> > In V1:
> >   LogoDxe module displays boot logo.
> >   S3LogoDxe module is based on EDK2 LogoDxe module and update AMD S3
> > logo.
> >
> > Signed-off-by: Eric Xing <eric.xing@amd.com>
> > Cc: Duke Zhai <duke.zhai@amd.com>
> > Cc: Ken Yao <ken.yao@amd.com>
> > Cc: Igniculus Fu <igniculus.fu@amd.com>
> > Cc: Abner Chang <abner.chang@amd.com>
> > ---
> >  .../AmdPlatformPkg/Universal/LogoDxe/Logo.c   | 198
> > ++++++++++++++++++
> >  .../Universal/LogoDxe/S3Logo.bmp              | Bin 0 -> 964114 bytes
> >  .../Universal/LogoDxe/S3Logo.idf              |   9 +
> >  .../Universal/LogoDxe/S3LogoDxe.inf           |  55 +++++
> >  4 files changed, 262 insertions(+)
> >  create mode 100644
> > Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> >  create mode 100644
> > Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
> >  create mode 100644
> > Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> >  create mode 100644
> > Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> >
> > diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> > b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> > new file mode 100644
> > index 0000000000..4463ba58eb
> > --- /dev/null
> > +++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/Logo.c
> > @@ -0,0 +1,198 @@
> > +/**
> > +  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
> > +**/
> > +
> > +/** @file
> > +  Logo DXE Driver, install Edk2 Platform Logo protocol.
> > +
> > +  Copyright (c) 2016 - 2020, Intel Corporation. All rights
> > + reserved.<BR>
> > +
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +#include <Uefi.h>
> > +#include <Protocol/GraphicsOutput.h>
> > +#include <Protocol/HiiDatabase.h>
> > +#include <Protocol/HiiImageEx.h>
> > +#include <Protocol/HiiPackageList.h>
> > +#include <Protocol/PlatformLogo.h>
> > +#include <Library/UefiBootServicesTableLib.h>
> > +#include <Library/BootLogoLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/PcdLib.h>
> > +
> > +#include "Logo.h"
> > +
> > +EFI_HII_IMAGE_EX_PROTOCOL  *mHiiImageEx;
> > +EFI_HII_HANDLE             mHiiHandle;
> > +LOGO_ENTRY                 mLogos[] = {
> > +  {
> > +    IMAGE_TOKEN (IMG_LOGO),
> > +    EdkiiPlatformLogoDisplayAttributeCenter,
> > +    0,
> > +    0
> > +  }
> > +};
> > +
> > +/**
> > +  Load a platform logo image and return its data and attributes.
> > +
> > +  @param[in]      This              The pointer to this protocol instance.
> > +  @param[in, out] Instance          The visible image instance is found.
> > +  @param[out]     Image             Points to the image.
> > +  @param[out]     Attribute         The display attributes of the image returned.
> > +  @param[out]     OffsetX           The X offset of the image regarding the
> > Attribute.
> > +  @param[out]     OffsetY           The Y offset of the image regarding the
> > Attribute.
> > +
> > +  @retval EFI_SUCCESS            The image was fetched successfully.
> > +  @retval EFI_NOT_FOUND          The specified image could not be found.
> > +  @retval EFI_INVALID_PARAMETER  One of the given input parameters
> > + are
> > incorrect
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +GetImage (
> > +  IN     EDKII_PLATFORM_LOGO_PROTOCOL        *This,
> > +  IN OUT UINT32                              *Instance,
> > +  OUT EFI_IMAGE_INPUT                        *Image,
> > +  OUT EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE  *Attribute,
> > +  OUT INTN                                   *OffsetX,
> > +  OUT INTN                                   *OffsetY
> > +  )
> > +{
> > +  UINT32  Current;
> > +
> > +  if ((Instance == NULL) || (Image == NULL) ||
> > +      (Attribute == NULL) || (OffsetX == NULL) || (OffsetY == NULL))
> > + {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Current = *Instance;
> > +  if (Current >= ARRAY_SIZE (mLogos)) {
> > +    return EFI_NOT_FOUND;
> > +  }
> > +
> > +  (*Instance)++; // Advance to next logo.
> > +  *Attribute = mLogos[Current].Attribute;
> > +  *OffsetX   = mLogos[Current].OffsetX;
> > +  *OffsetY   = mLogos[Current].OffsetY;
> > +  return mHiiImageEx->GetImageEx (mHiiImageEx, mHiiHandle,
> > mLogos[Current].ImageId, Image);
> > +}
> > +
> > +EDKII_PLATFORM_LOGO_PROTOCOL  mPlatformLogo = {
> > +  GetImage
> > +};
> > +
> > +// AMD_EDKII_OVERRIDE START
> > +
> > +/**
> > +  After console ready before boot option event callback
> > +
> > +  @param[in] Event      The Event this notify function registered to.
> > +  @param[in] Context    Pointer to the context data registered to the Event.
> > +**/
> > +VOID
> > +EFIAPI
> > +LogoDxeDisplayEventCallback (
> > +  IN EFI_EVENT  Event,
> > +  IN VOID       *Context
> > +  )
> > +{
> > +  DEBUG ((DEBUG_INFO, "AMD logo is displaying.\n"));
> > +
> > +  BootLogoEnableLogo ();
> > +  gBS->CloseEvent (Event);
> > +}
> > +
> > +/**
> > +  Entrypoint of this module.
> > +
> > +  This function is the entrypoint of this module. It installs the
> > + Edkii  Platform Logo protocol.
> > +
> > +  @param  ImageHandle       The firmware allocated handle for the EFI image.
> > +  @param  SystemTable       A pointer to the EFI System Table.
> > +
> > +  @retval EFI_SUCCESS       The entry point is executed successfully.
> > +
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +InitializeLogo (
> > +  IN EFI_HANDLE        ImageHandle,
> > +  IN EFI_SYSTEM_TABLE  *SystemTable
> > +  )
> > +{
> > +  EFI_STATUS                   Status;
> > +  EFI_HII_PACKAGE_LIST_HEADER  *PackageList;
> > +  EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;
> > +  EFI_HANDLE                   Handle;
> > +  EFI_EVENT                    AfterConsoleReadyBeforeBootOptionEvent;
> > +
> > +  Status = gBS->LocateProtocol (
> > +                  &gEfiHiiDatabaseProtocolGuid,
> > +                  NULL,
> > +                  (VOID **)&HiiDatabase
> > +                  );
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  Status = gBS->LocateProtocol (
> > +                  &gEfiHiiImageExProtocolGuid,
> > +                  NULL,
> > +                  (VOID **)&mHiiImageEx
> > +                  );
> > +  ASSERT_EFI_ERROR (Status);
> > +
> > +  //
> > +  // Retrieve HII package list from ImageHandle  //  Status =
> > + gBS->OpenProtocol (
> > +                  ImageHandle,
> > +                  &gEfiHiiPackageListProtocolGuid,
> > +                  (VOID **)&PackageList,
> > +                  ImageHandle,
> > +                  NULL,
> > +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> > +                  );
> > +  if (EFI_ERROR (Status)) {
> > +    DEBUG ((DEBUG_ERROR, "HII Image Package with logo not found in
> > PE/COFF resource section\n"));
> > +    return Status;
> > +  }
> > +
> > +  //
> > +  // Publish HII package list to HII Database.
> > +  //
> > +  Status = HiiDatabase->NewPackageList (
> > +                          HiiDatabase,
> > +                          PackageList,
> > +                          NULL,
> > +                          &mHiiHandle
> > +                          );
> > +  if (!EFI_ERROR (Status)) {
> > +    Handle = NULL;
> > +    Status = gBS->InstallMultipleProtocolInterfaces (
> > +                    &Handle,
> > +                    &gEdkiiPlatformLogoProtocolGuid,
> > +                    &mPlatformLogo,
> > +                    NULL
> > +                    );
> > +    if (EFI_ERROR (Status)) {
> > +      DEBUG ((DEBUG_ERROR, "Install protocol failed.\n"));
> > +      return Status;
> > +    }
> > +  }
> > +
> > +  //
> > +  // Create AfterConsoleReadyBeforeBootOption event callback
> > +  //
> > +  Status = gBS->CreateEventEx (
> > +                  EVT_NOTIFY_SIGNAL,
> > +                  TPL_CALLBACK,
> > +                  LogoDxeDisplayEventCallback,
> > +                  NULL,
> > +                  (EFI_GUID *)PcdGetPtr (PcdAmdDisplayLogoEventGuid),
> > +                  &AfterConsoleReadyBeforeBootOptionEvent
> > +                  );
> > +  ASSERT_EFI_ERROR (Status);
> > +  return Status;
> > +}
> > diff --git
> a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
> > b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.bmp
> > new file mode 100644
> > index
> >
> 0000000000000000000000000000000000000000..137f4dcebe4ebd77d5
> > 0f35ed3b31bf76c0f5f55d
> > GIT binary patch
> > literal 964114
> > zcmeI*zjE`um)LP-
> > CmE~SVz0nu`pl&EZ0BMdw`zPTz7I7nJn7S<c9AM=+F#*I*h((8
> >
> z@E(#P2?7V_fFLD{^4IUnM<gW@;0M4V_(#;g{@cI&pMTypfB*Bp?sorOUjN5`
> > +wK1U
> > zKkat^Ww&qV|KorE^X~u3N19>!_qN-
> > ~|GT%h?nVBU(cS0g=kD_#pSyqmfB$Q@dwi1N
> >
> zRR($E@m+>b8NPPAr=1LsGRVl&s|;^4yvy(@!`E*2x|88ih9?<h;`L32cNsoq_&T
> > Ti
> > zD6da4yvpz<!@CThGJNfJGP-
> > +zl;KH+R~g=9c$eW*hA+wFPKHMro@98H;Z25j89rtB
> > z+U?~3-PfZGPcpp9@Fv5%44*Q5?Vfg$&E2C6&3~^lyvgt`!>0^i-
> > KIT0%IlL1uQI&J
> > z@Girr3}4-
> 5KRwFplMJsiyvgt`!>0^i9m(sXygteBD#M!$?=pPK@YQj>J<98o46ic0
> >
> z$?z`2rwm^m<@=+&KFRPZ!<!86GJMML)iHlQ%IlL1uQI&J@Girr3}0;#JbgXN>yr
> > $x
> >
> zGQ7#~F2kn`U%NNi{<qzu49%9m%Fz7xF2kn`U%R)*oeYmMJjw7X!<!86GJM
> > ML)fL;*
> >
> zqr5)J@G8Tb4DT|0%J9_{>FcAsKFRPZ!<!86GJMML)fKlS^7i&5!>bH$GQ7+1DZ
> > ^J+
> > z72Y4^^+|?T8Qx@gm*G=}udbSWKFaHp46ic0$?z`2rwm_h6?*%6l-
> > DO2US)Wb;a!GL
> >
> z8NPO(vi+aCM;V@Ec$MKzhIbj7|Gv7a_4p{SPcpp9@Fv5%44*Q5b=B_aQC^>
> > 9c$MKz
> >
> zhIbi0W%%l<<m;onKFRPZ!<!86GJMML)m7KGM|pjc;Z=q=8Qx|1l;NwZ%I}Zz`X
> > s}v
> >
> z3~w^L%kU|~S69tHALaE)hF2NhWO(2G`+xlGKIC(6vcBE!r~QBT^V5vUApbS9nt
> > %91
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKw!SW4}S=h3CyotEP=os3Y0Y$K83)~9oBv}34!?n!~z5g1?E>SmO$VR1q
> > #~>
> >
> zA4A{{Yd@QWz<dEh0Rn{r^D7riAaI8Qh3$opA#jJapG`twzCaoZP7lZD`RiF_iI<O
> > k
> >
> znjhxeh`=gE%t{al1YQoa|9&etjk!+R<HO7N=Jm&(KTb)Gm~k5d*RKtvc;^Do6|M
> > by
> >
> z)u36kvZy(p*3D5xkslr^9HXsZ@)80Sg~=iam;yCzea#T{{B34We{<TnP9OTGt~vL
> > G
> >
> z<MU~u+{)B7D*<W!4S|}N`BM|;bk66Gn!Apt4e~)>^>ydIR6$NRgsJrfu3HO8?J
> > o$_
> > zHTBhk=Eu+Cn0cx>x?jI&Ij6aPz*}LB>lZX@{ObaBG4r%i(3Ft5IA-3!k$F>zo*!0d
> > z;jCh9fxq6q+5Ytf>SE^4Izh7unM-
> > 5l=~pkA2L(b$bM1Jy#`=N+VibW@1S(_Z&l(qA
> > zj%}l;*o?3--
> > Nf0<W*a!885YZ}j91hy7D2!isEwH`1kGcYwwXQs&9FhPbe2F*XwKYc
> > zE}e(vawFq&O7Lbr`(pmBkxeUs!>t^-
> > sT+E*vYvVGdEHAM)iLwuXW@y&bI4qJY<^T_
> > ze_<vkG;btKPO|X}6=8Xj-
> zV#Dg#hqjt^a3w==Nd!EzZjE<6Bw1%=`ZSP*?t9<=l90
> > z{~&8Tyr}D(TVM-
> f=CZ@{L!a{89Lwj!Rzb`RH5iWsDr(p7FJhnOS=d);HqX3Xc{)r4
> > z_CNVhw75t5(5yR2pqcR#W#gQuLsY&qCfm)}KS<=9Y~TEeK61@S`}|Sass-
> > _CtQPb0
> >
> zOw62LTFaL>?f3f!`IG&%^a8$RY`?FsJzjoJl3bUXq$kNW3GSPwH1n^bcHO`t=4q
> > a3
> >
> zH?StRFDBxCx=M?DY4kCJx4QBLG4s69Qi&eEkLt>&8=jrAL`>P{O?_98O)Gd~44
> > E98
> > zyUf4+fs-8AG{-
> > gJX(5@Azn8<ucN5B1%%KF!KDFtARFmAxi=;OzxuDK%XtcedB!{~E
> > zPLc22s@wTdKh`STX$e&TTOD3Ctl8n-
> > +^*owrjmWA>o3^`OC(4nGg=!o!><~a<TCn9
> > zn41NC-Ds@~C)4wp-
> > ?JZo(k&qUxT;Ro>1ZZ+G<z?hX)u0jj%C88(Z<Ryel=&@o5`2s
> >
> z_ewoZNljK67DS(16EB;;Hsz1<^ul#*XWV`aL=@C!Z<f9G_&Xw2gqRf7?0m=qzZ
> > 5f@
> > z3SJ*JEs>z<<VNd)W*9Q>xSuI?duZ}=Mw-
> > gk#)gBOB7Z3FS4nL*lG)9_u)nvDVY)mX
> >
> z<VxoA^WkIZV@gi@?}Ob2+m5E}7TWX*!)8rGzJX<|Sn?AcJkQQ<caLALNyj&$S
> > P{Z5
> >
> zuY!zO+o|>g*Xd`Tx81LD>LyqsIn{9fetN=KO(UK;37PjDGp!(I#5ai!<GU}?k1GmD
> >
> zO%GvQEE<!y=JhjA4^9X>7pvs8iDUBey`VCkzNh`mxXz5z(&IcFoAiz)>5a>6YRo=
> > u
> >
> zr$&?V?Xv>a&riH^t57!{GbNDKJb2d<31ees{PeSrjoq?)nU<OR`Sb%}W^VY{e91
> > 9X
> > z8}Yis(e{Y+rJx@dA5}$gvts7{drrAFaZJLPJbt;ZKFv!_!haX03!-#nu$f8IG42Y^
> >
> z+p6GNLfDYb<H;2!D<|8JnKe<<5>Z5zS#zKF8=v=^SK#fZ!(7~H%p6sQe%!(9SFI
> > N_
> >
> zPx{SqW2VxvCY#dvtBIO(BW9a;6Q(6fdnRc{w=u`OOmkYa4d$wUlJ;aph<k{c5;e
> > c)
> >
> z9V}ZSVQ4bO=LOBEm$~@+=1CbZs!t0Rj`szNZ~71N(gmd5i+zZ`R?L*+<RI<x(dIg
> > h
> > zM9sNXYF_;bvLop|?+(+Wmbjh<AK%od-5H$M#-
> > |%@Ujf=DVbChh<ipdX{3)yO)JnMO
> > z`OKlR%&YO1$gs-
> > HNWbiyO8?yM<@zO?75lKsC&K*viI~|4_yK99nE9}vMap?tiDF^#
> >
> zhGnIVS9EEE`XIMIJ)2$4;IrErwW7(Q2iV$IfYS3xR$<;t%>4P8^Lt{Jh*rhbc@M>Q
> >
> zUC5lQq@pT^%m0~}DNYh0tZvmRF>_fA>n=jg=xWwnLkw$7bI)l1E!?nL^yA@Y
> > H#KhG
> >
> zqFLPF(rq?_u~LPs2(cg=UB;};T(O_|BO6(MaAk?~_0E4S4Vp^Gq@S5qYimw&Ze
> > uJR
> > zrNW16D!K-=<hxzx#H1k^nH;m*jLpA-
> > 7;aHNe#qYu(0^oeul6ByeNW+~i4WO7<?534
> >
> z@w<tc4M_3fvL%w0P2VW{i6AXx5;JEu=X^X`A!aV^_VwG6&*Y@;)ZO0OCo;a
> > ~lN&#?
> >
> zwK4NjO>%X+c<ap7CN~<%YOM%yS245ryWp0{q<T9O$_^?mM)i0j{g^u^%uD
> > ?q*G*>L
> >
> z2QGOHXp)m`fLI<gi+8n?3~3YgS;lh#uF$DHr=2y?^0tk6=G6|TsPkKBcVD%;<*f*
> > D
> > zUoo@v`IeSQ7@FMif}W-tGU;dLD|qIe+%;9FA^FGV1!b7Yk}}&rsk!XISkok@-
> > ;)??
> > z>-
> >
> 1Bbn#!MWkj+c4)s$_UeY3o_Rx3i>S<IA^nk9;s$XN4A#@yuekV(ueDW>UXGT~
> > @x
> > z%q%@CJ<UvZDwE5xF1a-(yK3c);n{-
> > Y`kOK3lUtdUX)oRO)gGK%7hQhT3S>oyyNj98
> >
> zvqSZ&Vu?&^pF5@Pq=H0qRUr6C>1dc0^Vqz(#d@v3{mDLZz1p$)ZkLHhYLy>N
> > -F_x9
> >
> zbHuuVG4n9G^5I720l(hMvLeJC#ms&)3wB2RN5e2wJ8lNe?zS)`xr*8uX3&b6*
> > |S{X
> > z3TBL(2a{KfnLGVN{=%4P?-DAC$-Hq=u2U{<ag#jhJCeyqHa21Q3C+fq-
> > OyaerE3K0
> > z-
> >
> 91W^9h%JI60|l^&5a%Ohm0*4@sEBik=Y3w<(R*dHe0^=H^Ph^@*m5DmT>9
> > 0<7zo}
> > zIk;xb)Vqw!V&*!x{e-
> 2FiiF&2T{9n2R73Re?gmH9bC25P8h;zj=B{_KtVQlIX6n7|
> > zkk%3jYk1jsHfS2R9f!Fo91k;N^fUFy5-
> > vP@+}H`F5hANmxS7VsRL?~*bN!Gh_qSW!
> >
> z2!qntaN{jCHRJO)|CV`huH6>oZjl*<fAsE$6(R02W|~Kn4Y4IMJECMS=VeaNw+
> > Xlf
> > zoqiz9m=!Zu-Z)9tXy|E^y<p5#cLz&i=6bjNgvFJ+nk|x*C*;Dl$KzTpi$AleY5f$;
> >
> zx%L}XF}so0J}mcGPOA~!R?Ivd(?9uzHu+hUd5_!jj({wYFf<j8>oHoZ%)<(^1)P6l
> >
> zSXM@in7K3W)(BTpJZ@CftHw<AGSHHkX>3@&9Q=3G{&1^Zx<ir2lQd8MXp-
> > vwH4;@~
> >
> zjPdE)f6F|1=aja#b>{kVw=Y={;<jR@er}<GXn%yIJQ}1ADw$|nBE^v;_@LHb$=y
> > %b
> >
> zEjGzc*+h_@TuI3O=~o59h3Af+jL>r3n5lI%omQkR(gR%L$h<8}C5*Lc7F__62XZ
> > z)
> >
> z)Fyw;Zv+|VlF!vfsc2;t>Q+Bx_6wVzn49_67q|ABt36hP*h<W7%2)QiAEjZ_Xy&
> > pe
> >
> zOGJ}(=cPf@I6!OGR#9KwOkC^(2Ih5RrgnWRSL@HhM$AkLt)f)aMU*hs7EVDo
> > ^EvwY
> > zih>7rr4d@q)MjSpE_1KmYNbqaRohByOEI%4^s;CB3x;*{x^m2HeB-
> > kLPRJx?*0o^e
> >
> zd`ErE%(a)gtWB2EJNy3GOu4nT4X)uo?lYIt2tCQm<|gc`Kq1ZI@ob6QQ_Pg8={
> > ~u;
> > zl{A}@B{HuZ+BLO7b8-;nh0MPjGhgKVbo6&@&fQ7NF4%u7&B-iiS!o)C&L!-
> > ezZpY~
> > zoEJJaS(bdZ*(}JX{?mePkj~s%>mAZ32eV_|H#wGU&%8D{<I~xbfmVblDSy-
> > 5+P+B`
> >
> z>DOYNlFe>Hzi|8de6$kn#jFZyiS*0QeGN~JW$J#g%E<<mO$19{dDNhseQd7X_
> > |crZ
> >
> zEBxi<wB)N}X2F576pS3$4A&neo9%B>7Bm{AL!2CoB*mVsHqKY#liPrkHE(N%
> > R!1&V
> > z<@FnlM9Yd01;uZBr<Hizx(mfjsmS`V&zN#Erl#I)j3qK%$&9J-
> > iDKEhKd#M2Ro@*K
> >
> zzV_IqV`jHK1!wN$3zW&W*T&4EZl?0fJMznvYVkxfm3HBE7maFTlz^n09Gpja+
> > 1zCI
> > z*dQtWWi#@1z={ytjG6M3YN?afc8R6YX?2!t3*t2M>fFOa-
> > y2B#UTMizRO56d*P3Ir
> >
> z*mPT+?wi$z(C^urP$gX|{Sgb}GTCEuC!ft4w6lw1UKHGwj;51hN;#Hqe7bzxzIH
> > 4Q
> >
> z(9zqQn@snNBgL9y`4X`r#8zWw$wRU8{Q*nlTqe>mX8)b*rWF?Y60fMn{i4@
> > @y;jWh
> >
> zk6w3aD5~sd=DQd}(d7Gm`+Q>?mX70?yK!cqFp5A@jIW#znb_!va@zV5wce;Y
> > R)pAW
> >
> z%q$3+`HrR~(icuav&huQv@g`Jb9~J#YRw)OzV?{WVAIZ#<7V$rvez+tnB*|Dwx
> > 8)_
> >
> zQ_?ejJEG({t;y*lqlGqGmu^{D%r?w1s?fdGW?z#XPH3^(xKXbo&`FZpjhXiMdfSc
> > 6
> >
> zp3$^KdLF+~<!YqaVK}cox2!S0&)D@}jk>jR%(PCZv@~gCaY9k%*xZgmO;Tx(HiY
> > +2
> >
> zBP0pucj4`p#eKyvH5tzzG|AGjO1r`>|5MWKh=3|4v+>~`uK{({!M&j;+tx1|GfN7
> > *
> > zqC!_xij@}0I?5@(q(|WFYwUie`-SZEsI4w$IswcJnF8x<XL`VFFA#^lxaiEK<M>=r
> > zyKZcek`@{h&7HRDfR+A+`<dzPHAc%eCrhMXiCIa_8b-`Cc!-%g4l#4$;`F-
> > vM!M+r
> >
> zI7x9jVMT~d$4uqUlPO{@?pY%J8gk1{ZM7+4rlxY9=fuqHm)XvX$2}^!ifvcnbb+
> > >j
> >
> zt@hF+mG+<edeOhSNB8l;y?J!)R%JWGQE&f@wc!`*F7Cbr7QUV=9xFoF70z1g
> > `Ms#L
> > zCflK&FR(PM-
> > m;n(XLpo)M5!gxZvip0m$2ek8e1GUFJ?MbV5MVoC(xz`)`P`3Vw|yP
> >
> z>uMCOofvDiBS~}K(rR1T)=bA^EQabav;3?GvGJIhHlZn@8nx{+y!{HCwr|wH8|-
> > JE
> > z9=^-
> >
> |)T(OKuGM3va}Q8@2<wEuC~}=k*NM!|1)%dv?5<xNckO)Y+3f40+nbL14o2n
> > N
> > z%3CEDQb(SOF}pnKW2QX0^1HuNJA<t@vhyaW5o^_crgun_Y3-
> > Is&wp1jGvkn!X&RHn
> > z!&rLtm}yt#<O;DHP4r;og*&TO_Z7sw#y{P6+B*Z)eMrgtf<{w__ZKt0-
> cVpuH)`)T
> >
> ztq5WEGrL%CuiUC#SBRO;6LvEP=axuc0(TWNi#JBCs@IH}c4*n9dt4{Tsxi|!(p4gJ
> > zUn|1bd288!91rb-gw-ZDjjv%U?YNgz)GJH(h1;9+;C;_8L7F#14Ne1-
> > 6(Q6DJTKXw
> >
> z#5S7DPJe*QIrnO|(po=ms~w()4GKq`%BF9hCDP}nILw5(X~&%`wFx8(`7`>A)w
> > ~vO
> > zjN0EZD!}UfOs5J&!9gr)Vy2Tw+-=K=8!l~eCjE)#VI=##d?{BB-{d(-K@5#LigAiw
> > zO3~teWxD-O9AblYr!&2&-
> > o=U#dQ54T9GZ`L|87z*f=#<d%yc@M`azf_(&xW8%=FB|
> > zD=~ARNJqS;;6#TgI7ngD#7rj<wQt(ji{RDi6Z@fejG^{ZDV+0T_jqi+a~gI~3{|5}
> >
> z^R^;HK4u0L$2v0j^_ZFVJVHagbyy<((hh1G4Td?_ikYX9&FD6#cw>egWzW#O>
> > WJ<3
> > zuHMhocXESmTHR`5ro-XI^}*&a<Vzi~tLCs4cf@-
> > jQgXDX=4NX%*V0pYomx}*EV!_C
> > z8bLGsSe(17^fT2na6?Y?E_g|>aoUwp1Fsb`hmCYc%p--
> > #mi%_ibi#v@J*V~uyZ(X6
> >
> zc}kGqKkV1!)RE%Y+pkZ3t#}~Fq)4|qp_KLLQ}EO=vymI!fY!@eINQ&h{?>fHD*t-
> > S
> > zG|#AJo}y`q^yT8T2csrlFJ{UuMA0+P^~qzlnB&b*E2>e!R_<qdKhdM~J!)d6!(r9
> > w
> > zzIwE;222C1Vop}zPwc<dp2xJ@;vK{E-
> > K|bp#juxO<#hhcM(&|n3+HN2{8W}~?XWgX
> >
> z&DhG<faFn{X2nwvpVG5p={jydW<Gr6O0T|^sLecE_}cen95=J?<@JZt2winP(>
> > V_r
> > zN1(KB^mA5QQNP0I_4H7-w~I@yzWi@#NvmNSN51Dx=&xW$q}`-
> > <5wPaiym=1RG}Pvr
> >
> z!tcjS``}#7_j5teR2M9&QdU{_C0Mkg>4*A7yVujt1tMmqYjmxc>4i+S<5tnnbXr
> > Ut
> > zfu```l-
> F{t#u2VZ9WVX452+<__j_7#wmM}tY@<$g+iTjZJ*m)X8vLf^qxV#jr>&lT
> >
> zaz{;8)~?gfv=7ep_MvrHrZE0<YeM45_;q5YbFpNSqsfGMNE07lv?xaXOd*|pO}?
> > Lb
> >
> zdQj_2n0IYgR}nLvES8ktxw1HIPs?vq&Gbn*>2lDUX2>y&$LS1jY<nc$tkBB*wzz
> > Dz
> > z8F2Nh93j^1n3*;N$!%tzdIK>t-phuxKN+56uP|AtnQ$6b2po-
> > <w7F=JlF4ZfYqKZ6
> > zpKbi<m*OuTGv%(u?+-U(>fdOrh?&mr#%ik5LhveySu>+m4U-
> > ZtkG@4%W0I2z;hP&C
> > zw@%~P4-`$i-
> > UDwl;y0ezF;lNJdN<$(VrIVUB0RbMksCC9*IaG9M$FW^&$%20^WBGz
> > zPAXS7v1ZInf2;R+kbApJI#uefyypJQ^?HYfOk+MfX14o|5{sZjl@ltHcQ-
> s?+_idg
> > z=#53aD${_?jhVTUR`0C6ftYD_!?Qm>=>^T3j+vQGe?jxGW2RnJjOv-
> > jF~^OVsqB=7
> > zS;Wjq70yMX#w*tu>Q-
> > QOQH}cCC$BezuAG#8TK<BQ)*NmiW|}*NY|Px*(W9XM-uuR{
> > zSLkQv@BNB16Hhx^J+$6%#HeGlV`iM68PodV&-`O^Z---5>5xUn4Vh-
> > cN@~Km#^$1r
> > z(jI-G1jb)v8=o+HL*^Nlgk)sSon@Sm%!`>;qf)YIRWS9ejI{@-
> JmR$SV4U}`ua9aw
> >
> zhzV<UqNJr{7tX&Cl)Bee^DFW86k#I6xDgrV#!Te`l#$uVTSvVf|7y&1D(qn(^hRc
> > 0
> >
> z^qIh<^?363mM5&1ZP}Z_)>^Q~((77RiphR0Z3IDaD_@|nw(43j)7q*0C~>}rX?
> > oOI
> >
> zoSTlB^_jDFi9tzEMpulPJ^lRG+~H3}%uFi%G&fe2p18P=Xe*7G`&n1Xr@2kOY%
> > W=h
> > zKe5?q3(zWf>!99>2m@3$EQoGWea!gtvrodHRl$-
> > EH(9zsKhqSl!b_&>(l!ihxq((4
> >
> zxk5kF*b%5%8fR`bX68bscS1k8rYyV3q|%Q(GNvpMMapr~xv4$v0gj6fV{%At
> > XK0eU
> >
> zbV5la{m@qDSeJ5)7HTbKp9noe&54<2_>p2xPNdy@%rrVla>6NZW0Z(f0g0Io
> > P{rHo
> > zeWPvInI8e2KzH4kS@hjV6HMvln4jO&n^ru^A7fknva$;m`M8kuGmRK>-
> > Y>=>=oVt8
> > z)q{6V{pB~9m^t)>;xZ3fU3w~~-Yr;dH2R{%g+6!d$4sle^r@a-
> oy3(c;B*E1WnIjM
> > zN$Y?|d>fuLqn~;l+ia{+UA&`=vz1i`rbh*C8B2*rZQ>SUrU`2__{JyOfr+;BY+3R`
> >
> zKeI%s{4>uV=AqWK3dgHedW}v$v!oI9k#AYdTp?oWKad$CY<Sv=FS#aaUIB9A!
> > I`Q!
> >
> zW;XT9`fyiM4wDkFwn^O&SOG5I+n%HuPgtvT`kDFrj&lVPC!S6dGgFiLId;UXIXij
> > 1
> >
> zm}xfNQ^^yHJU9Kx3Eom0df#eHneX`7w|J>RDFLy<;AAIl#lL>fDwTASs<q7IgMG
> > HF
> >
> z0QVa)Q@*UB0ueKZA~$x;7d|$Be)+H}Sd&Ait9Rjkrdq}Os&0PiS^rwyuxQzc9y
> > 0Ie
> >
> zy1Dbc@oD#MAhW7WVTe&f!nr|&Wp14X7}}4FO!m`O{=$_H8+3CqGxH5MV
> > &+ihzZ5f{
> > zU%nr#y4&S%e#~^1Sn=3A-
> > _Ja$U#c4#N#RH)WZqNEG|x@y71J!h!e(vNyP%(GU7{MA
> > zPdgIE>N|*;da)GZDz)1>oaiBy#k^VlqRs1F-)kiIy^DqPFs+I^XgCp2>1R$4loIxQ
> >
> zpc~R0Mkd{dWKHU`>)K`a^#vHDl6LaX84EtM`BAHnrI)?c_tTe1k*umWb_KQTZ$
> > sUP
> >
> zMuPZ$4>3~>n#9bZ(1YTRYggKA>)nQRKffI0G2AcHp9&aq6OA~n;3i{cdYkjG?K
> > 4L5
> >
> zPfVDxlH32NbpcR2I5+osMpd3jSTS?xXPO<_sG5cs&u<}S9+Lb8Gm4ayT~mGA|
> > 5N?U
> >
> zq(;}f1(o)>{Uz|CuIBnNGufn|HbtZ15m%7?el*jl)(M%%d_Md1@8Z=u{?!`yQN
> > KRX
> > zmYj2lF?yB6%(lN^eQ;V?#xGIcLd-OSR8bpNP7D<-
> > HzEgPW_Hew!N*HS!xE@Jv|IUm
> > zKxtH{cbh_VVbi?LsA~qpZhyM`d1`(?(|(3^SPJfUCsUnf@v-
> > r!IWC)N_QK0nv5`+b
> > zPst}!+78o-NX|ZP6tO~Ke{60gG|A<8V%Sw$3-
> > &7?vm#^G`HA99nyfK%5$BxKvNoIs
> > z&9ddD8R@3}Qp`+mZ>@KWEt{yhd-
> > jgdwPq8nNr{=pV_Vt<ttuV01*gIuqK~(eYlO__
> > z)ICfp*#0{hwaO#yJXrC?EBO)2ikat~v|R*YarEQ;mnf|bx>n3oj;#A^{**E$C+6zg
> > z{vV2&iCTEtW~_mAW5mp?+n<V=>YnG^z|)<U6%2AWbf(UJ%*=m-
> > aEv|UShv3Osf1gI
> >
> znN}Y1&(DmY;^u#^G1J771IMwPhcWG}QKzR=(0aG1K$^+s3VQQ<e#T!#KQrx|
> > Op;bM
> > zDwlp<rd^}f+T9<Do8(2Ecs@9Vs4lhLnMMUjPEeXxfXeHp)(rYe&~^p&(=Po-
> > a<5$m
> >
> ztkSzyKhrQxzEPjAIZ@Co_l;M1)BQ}jhbRB{{r#W?&1_`Q_O<nHv12<eLDN13TM
> > ;vz
> > zELs;GqQ;Pw>9$2%Q-
> > 6S_Zf(iTXa6RwlGSYJGuBQlE=#NNIaMVTv0`R(Y_6U1iRy+n
> >
> z+5Hmb4a7`y*D}Lt>JS%3C~A*e#nwaGYf#_q7j0gho|3wJ(M)ysnTrhS8J#+}^Eo
> > 0t
> >
> zkNKNwgu*G{X`yz8x$QZpUQ&MDio9}A8hg?)(l<Ff_r<>|c1O?8>=>+5l<~p26_
> > 1>9
> >
> z56!KZ*>nZ1WX^R%eQB=)SqopOpJ|cies?nT8OA4Vv##wo>ndq;Lz?9yVHsR3
> > W~%!i
> > zy{@H~&DtC~Zik2H@B91X=>4RF)zhqqnQ=Rd%0S(3g!;p{7XX#U;qXLRi6)<q-
> > W9Pf
> >
> zYtdqxpHv)&GMEM#tL(he3Ynaksq74g3|S+mpXMvG<(qTPk`>{c${cP~Fs>Z|4H
> > =)c
> > z$}niwSMJ}And$FG1X#|f8Z#f{4)f^m<@lXBBjUInhLQ<J+{f-
> > 3U%04<na;O&w61B8
> >
> z*<jRLQQA11C9KkUIX+~_gB*3E)@ru+p4FnJJ9I0U%?Slo%zU<Q)JaNXIz!IQq}5
> > {l
> >
> z$aEKQF0A!qrj>>G(REIZ39dIdZQodtRl+@vv3TySe$nRD>Srn(<+r!w_S04!3Nz+j
> > zH&<h(tiky<p?VsiO}HXvdL0f$aJr5Cl+y~89niFe=ZZR=UvztapRK$4zIkJzKn~kF
> > zy%uimRjfu6i(B>m+1P^**~*W6-$Kl^wy*S7quy-
> > f*lNsFdr8F`lZ%=8DiFWpB$bPq
> >
> zKlb(H=mK4kXhqEQDusFA5+v>IkW<X^omXEW<yHFhWnaA?vKB0SAEQ?H@e
> > pjH)m@ne
> > z*I*%S)QBmkpkp<NmyL95JzD$Z>-
> > 00Tt+3e+r$wb)L(p{Ee!Ao^$11qqcKC4lNWW<F
> > zYV0z%8Z)D348|_UTrGA=xP~K*b)o$@?nS_~X3o86{yaZkHrb2uHa~40oQ7R
> > @D;mve
> > z(7D>y=vwbJ?|XkIYX#SdnbtnY`Q>=6F7=Ib7V%_7#LNlDbRvx-
> Llv`+baTz2CT51s
> > zY?{4pDwo!f)o#Q)IhpoX=Txf7c-
> > dr4+oo;LGmg1~3SfoS;9~_8R#=N_K|FbKANd+D
> > z5l&wxW}2JlwGM^veCljY^`5SUm^t;BOc^oLKFyd0psuPpZ9(m4+R-
> > `x?EbKF%eYrX
> >
> zlF;jQOb4k2@v_O|u%5da$(4Sywd29L^{IK0zzix)qWWL6*hl^mfcip{xmSsq5}}L
> > @
> >
> zG!A03^{ES*UW3Rk{>%3osX?N6V@eN8C*?euaFQ}&ru{P{xt!I+OglQ;*Br);_1
> > 2Q+
> > z*ju8lQw!r|lfQi3-0C~lRiJSXXas`d?*n#1)|$o|pp7-
> L*{bB)GQqs7#LQ%89%Nwt
> > z>C9HF-Ca3t->7^N#oa$+@!VVCI*na{8Z-Cl-
> > 9pjLL*3+}yC}L0I&M~V8Y{nMkSXYz
> > znCbQq&GS8dL3llvv>tc|^AfG+T_EqX61{4C8=sdc{bs|58c<)i5}fLo+0|jI!yA=V
> > zG<l7fX`RB5J6IBoq8ZI5J8j=sPuf-
> > @7nw8`&%G6{WNyq1m%Z?~<5pj<Gxcz2F}j<&
> > z3;D65v-
> > fq)PH=d%m!7cpi?Lp^yW`9Y<e9R}<!Hn6t$Nc}xhAgWf}PP~G?m<HGT_7P
> > zey>=x(;b!yMy?Svjs1`0q}S9~ta;KtYZv|P?*ZvSA}Ey$k2-Ev-
> R~=$UNY&SZo4H_
> > zG1EOr?ym&qvAVAg>sf8*Dh1)h%<wA}lY~$EQ}Z{OXH6Kn+U#4#)}L9e<M-
> > 3d?KV=g
> >
> z;KzDp$EEx_t`IY&30j+{=AeY{o0yp|SM!|(G1CqyYsO5!blr}EcVw<z39y&Re?#;^
> >
> ze(B@o<#0I4<5lE2Di05PJBXIl@U4BuDv++3XAVT#+UnHG1j7m{+3J4^E=MVQ
> > %<OXE
> > z8*0R|4yNr!lWbW3c#-
> > S|&R*Y`#P?j~anWOFkQpC8T|5@9$vD!eEv#_$OU4~HtDk8X
> >
> z7cuis$4o13bal?SAL++@28_}KvmwQ78e!efR9AC(dGqoy)7tq+2EuJnV60i~Zy#
> > D8
> > z$iGL-%-
> fik6z!OqIrOSJHg`{G?y|?p=SuJYJh{^CG5eYMuR2LR9<JCmwC#j+JYTvX
> >
> znznDlf4grPN4xE13u|v|!fPa{sTb_z{b?#ze)223c+7ON<uoVFYK?isOheHsvT2=*
> >
> zSCZ*KJB6HEO0An=l6KJaL#CFnxq<m=)0`z6f@X7+{u0~<p`8N=x8rWcm3`0<dY
> > aO-
> >
> z`cH?s3N<k^{*srK;UVYoh*~eLKDOP_NVYqF0;tQ0Sw)kztu`ZH`A49N#Kwi^e|Iu
> > m
> > z_QK;%-`<Fs-W}h1N24xg794^Y{l1@X|5#6JF=qYFw|V8-
> > *cd{!o_j^@y8T5m#~E#P
> >
> zmX>b4ZMv&lUJ*0XQp%TTz71YDW?GfH&6JwHO0?=sVy3}q#LRd<9j|58nCXP
> > tChhFc
> > zx19<?rdm18wySSmQ<3d`zY?5dx%-
> > $lLXcb*R~UxKWSsub(9DmS<0bQPmH8qavKEi1
> > zF>AGcrdlh*ESNQP+_2Thh?xdyK4yB|%*-RSoZzP&BDa;q=?}M?aL{g-
> > JbkP6I@)G+
> >
> zJJYU6uvE5zX{|9>P6;K!yLU8dMUKNRe+B5|R1uA6cFa_7J$u>DUXNP0tSz4t<
> > =l{|
> > zUxLzrR-Q-9G(go@(gZR4S#Zr7^`PQ3h-}O><5#-
> > @avAVBxygM0P<C!i&8(SMCH8ea
> > z06V&C8)*1%`K^3d{Q0&nQ``M?Rb+Oo(+kPURadz2zn6@e_9^-
> > %CvyU@>Q+0Gm}$u6
> >
> zV&;Q;{G<g3DP}Vc$pLn@q3N|e%(`4|ksBjF<aWsRmh#j7;rrm9$ZXe;X)IQ}9iB
> > oM
> >
> zH6tguYbk{raYy6E;rB`1M|F};KV1cy88fqIYx2*^j!L<oykN{UpWE4{Un3Rr$yxT`
> > z>g0IN-
> > 5)cGwwK|%lY>Mv;{LWpQ!rX^XqL63SUzStv8b&Jayw6Zjk<l6>JU~CYdm)l
> > zWcGOUX77DPQ>$%O);9cJrUp!^k}^@#d72qB^QYpoM-
> > NIyn^_l&na>5`+pL~`#d&VN
> > zZZZE)mdgE5&IHNNK=O%jd81R74-(-DE;sIU-(F%<`3<#$T2W$vOpB?Gna-
> > t^bMnvf
> >
> z^_%mpJ#mJNX)Ta7<Yt^!51sZ_*R;uj7HN%~ZTc;3Tm72s32G$sVy3lUn;A6Krm
> > *~c
> > zrkrH*p`50qIfe5wKdR`bTlk4Et-|qe&DV{Yr|;}vdXdD5nS~pxd@K`(oPsuXA?`(|
> > zb0)eY3nfR{S=pQ5?1P_lG5>m#x+lqIY~yc~ob?KuNjqNkoSs=R)2v9jLyjb$-
> > HeOG
> > z%;$ssd!@3q%?2-
> > Px|a@_+d4Kky6kC<u;G(48|AGyv!kq!nLqg>s`6Z^pUn3yY@L^B
> >
> z)js(rdG%Xt)J)yO%vquA9F=VHj7o7rO}MdBQ1@z?h<TA?^YlWdo_ftWjDRm+>
> > GkAh
> >
> z&kfQl9SzgCZa;Iym|429>F07)Z$Zo~J33FZ;>|H0iew&~%a?t|D^B}|5ASE+B_H
> > WN
> > ztEnbl1~>bDMZ0wBM~0#}W{S4aJleGz)gf%t-
> > T2D=Ou39%bgobmw~v7`PUGx~qDi;j
> > zoHM3XJQl9cj+t``JY1_X-
> > mc216lt5ace=$}n|v^HXkLE}NVZnJsV+%*?u_&hJAgHL
> >
> z+6(pVGmJ{FH|a;Kb920z&s!(<0_1SisJzBz&uBt^_bgX+!)*5BtHn$?qI)@fr0351
> > zgpyYyrWjEDTXVKCNxE!CpVW-kaK+a43Db-c57(L-
> > H&VM=%uEwH=ho>*80Rx(1?HKk
> > z8D$fGRK1il&^jH>;fhnZ#{76jCBMMd-
> > ^rYy8F<qXH3+#3<t@lA&@Q1FeK0k<)~@1o
> > zjQ`|;f$bv$=iN|Ww{PhouMje8j-JBmU_`N^pCby_<%~-
> > NHg2&=8?D)q>WSyS>K!V{
> >
> zyOldh#*Udk))mkBnQWFwMW(=>PkY9<H0exLEnR$jpUZ6UlsKI7dx0uKam*|`
> > qAd^g
> > zvtwqsvAJ>C8gGLtoz8f(izSy+Yra}g_RMf~R?K|<$lk^suA+F{e1uOLA-tGiZ)EP>
> >
> zG@U;G%VOs0*MZ!thh>c{=P;e0Q<;A1o~EoPar8A}@@lmd1I7z6LmCHTCF5Jp
> > o_knZ
> >
> z#WkQ{*#)B|z2$Lp;<2lQ%uDt&WrNzsg{}0D(aDsQ(pF2%w5u*LGj4ISre_@HH
> > sw%t
> > zqmg8&G-
> > j68_S_ZBq^?|~pP8f*&sbI|uM;va95ZLt!bKmxR?N&7%ff!<+8s^5O|N)|
> > zQ!cSZMS9x{=e~OzM}hNnX-
> tbZx*%pYA1OZxSeoxE#>{aWmxaviX|qh3)Xt8}s9-
> > uw
> > zs`7}VAeEUPxl+tDcGF8^=8t*qVJ=55iiL$&-
> > q4)Xvp2Cg%WeAYStp*H%8`c{<4IU@
> >
> z@%WsRfcd@tWUW_>nM1k@LuQ%PkXrRfzO=IMglYY;m}y;#cA7=OnI!k?iP<8
> > F-*8W6
> > zc4b)G`H7Ot??|E#-
> > qmDb?CGSdcTXj8VCFOCN_MBeaz1m}b<pgNJB(MWj8|0SFx|fu
> > zGt<s&V6i-
> > Au6CQI721OwdtV$WtQ&?(;Tksiu~}Dv)LvW3W*5cGnQJe)c&@I~y4NVI
> > zSo6lu+qmpF>(H#FL~CB&v`?3mTlAT5HGe8*+P$|GVx|N!`$|_-
> > 5}C<E@nNI$ZM)3+
> >
> zr?ag9J^kdJO%;WnuCdHHcAhGgM1jL}5qGNKkmncrnFYT&U~F0bSSJiu>x>)O$
> > h{RN
> >
> z{Fh>;9Woc*pV^}>+u1fnmi;A+K8eZevYIN%nO`=_RiV3>KjV@^eKRSDne)%Elm
> > wV7
> >
> z_cIsv7D~2gQty{cRMg%ux%$dbk+8K$dVn~;Dp~87;NbKt*63#nZBu!cbT$u8H
> > p9|u
> >
> z#uo<ZquHmmMK}I#`N6qUH7o}|X4af4EeQ8ljG0mk_sar_x#Ny&{Nib=yfW{FX
> > )fE;
> >
> zOae8tFCH`P;2<VW!zel+YH6Dvttfx0@DwY0AW>LUx$(X1Txx@~_x#vt=I(8(>|%
> > <z
> > zFW7y%F|+QDG5-SAHDjj#q(QstTsLHLf2Lg;{ksLRXtkL6BUMQHniX-
> > ZAeUO?Y`U5?
> >
> z$?e=eZO?a~uccQ+mfS+)#mw4k&3(MjuK$WL^I_px{ItKM)$;Y`Rn+D%@xRf}b
> > e@#j
> >
> zfvguZrO*0sl#n?yj#WlX$$h(@pPAZDB4)P1^;M*zc5P{q!qXr%N6$TjLtOoA7d
> > Osa
> >
> zEoLt5WV$EK`pUT4YhN}qUc<EiK+G(CQtFy9Q;7E;YOT$c(@XNhlwmQs<EP>u
> > Wjkk}
> > zOeL4wJDKkv;kNK{uBH0ViJA3B{r&N5E&;XnmG-
> > RN`Zjz(Dqgisx1byShqTrjsmO4c
> > z^nJ(7=a=KR-
> > <djltQ<3&&SuHOewzZ62L$J;epp!c_`W=BJ|7F8A6rqowzNpuRiN6h
> >
> znzs^mxi0C!$_<Uy%C8bLXYZ=h+Tq;IV%Pb)chgL`bHapfIA(qy7W^IC2mj5AL?<
> > UX
> > ztAd84;rK}cnf;LTna^_#SDuVZYDYUYsT;B%c`&b)hpTn#(#AhfbZ}nZ7Ze?{*3{qj
> > z*|^)i<jcp*rgB%Dw4YX)UkI6Zd<`gUyIUSV$uEe?FJi{Et9|<QxBTMyy4!X-
> > b*Uw1
> >
> zH=D<8A3vnqJtx6w{l34ck_TQm#~%)grCoddr%$rK4y4wgOUKOp!?&75pSiNv-
> > w2t+
> > zOtr$?-
> > ptd!`E6nO+073bn$i7!R`i;;MW@qV(rbU@v+HnIrdL++H~c9pq@Br^96y`=
> >
> z%q5rOJ94X=tOm4|&Sy3|=H*??W*f|~Kd;W0f4ZW+hAY3}WAiYZ+aD)pR@Bt
> > XFJd3x
> >
> zw$)AzKE*l9p9WdsH>9k4hShAZ5HnBf1x)Ys!lhb$ap8?0470N6T+O)3<zv^sdK
> > NM;
> >
> zt_v(L*Bf7hA4Ha&b2QFpuF>?2uN<l|v*cWaUK3=lL`&K8f2`BNZ0kkA9xI!h1#e
> > W;
> > z$uPBL2ObrP=N9R2od`3>_-_m3O6z{+%lTdVZ{d-c-p`a%0_(KA{Ff-
> > znE7IFtMRU!
> > zzWgY?4WzVo{8GqVdOma6&v%sK6nyS_PtW`9IJBko3kq)IACX@*w*MAx--
> > Dc4PXFZi
> > zcHw&a#Xr*Z%Nz-
> > QYRudn?2XO5n_N)rQ(yG@TOo64%*@a(vZz}4S55|RDSZ7(UaN|d
> > zg%BtZ_%LrTy<~MS$Xxu9Np{xS-^Gc{oNk{uI>{IlHy|*x6!|y;r2_f03Ky^UrCAI<
> > zH_g)_c<0wfxdJpTlv|nlwF*JPcP{Xo=i(}8rw#HZj?TXe?vtBlo2hFERMajOLBJRI
> > z&5*hDe5N$Kg%7RuecVrYPjS3PbRZ2)z%4pHfIx-
> > 7@1BaQ$ndmr$T$6e`S5(+k2y?p
> > z&(uW)Dry&tAm9lYx0PPBI-
> > ghWWlwoO&DKNmZD?h&3(caFnU=@R%(+mRv)Vr`@XH}{
> >
> zg=6!kfyyIFKAgw;T;%QJ8V^CcnFw=#8Tr#qn~lGW!0#TIOCzn=tov))Y|(`TDry&t
> >
> zAYcnTU!?mrW2JWX)ORn`zF6)338?jlnF#zff%|LPY|(`T{#w&udl66tF4VqQ?fnU
> > ;
> >
> z^@o`V{5665Yuaqlg#`Xu(_niMPz5g3zF6)338?jlnF#zff%|LPY|(`T{#w&udl5hY
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY
> > **
> >
> z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|
> > 0
> >
> z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I
> > {
> >
> z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009
> > IL
> >
> zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*
> > ~
> >
> z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILC>Q
> > uo
> > DNG4Z*
> >
> > literal 0
> > HcmV?d00001
> >
> > diff --git a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> > b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> > new file mode 100644
> > index 0000000000..b5eacfc5eb
> > --- /dev/null
> > +++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3Logo.idf
> > @@ -0,0 +1,9 @@
> > +// /** @file
> > +// Platform Logo image definition file.
> > +//
> > +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
> > +//
> > +//
> > +// **/
> > +
> > +#image IMG_LOGO S3Logo.bmp
> > diff --git
> > a/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> > b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> > new file mode 100644
> > index 0000000000..25b46e4bff
> > --- /dev/null
> > +++ b/Platform/AMD/AmdPlatformPkg/Universal/LogoDxe/S3LogoDxe.inf
> > @@ -0,0 +1,55 @@
> > +## @file
> > +#  The default logo bitmap picture shown on setup screen.
> > +#
> > +#  Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
> > +#
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION                    = 0x00010005
> > +  BASE_NAME                      = S3LogoDxe
> > +  FILE_GUID                      = A3193794-FCBC-E9A4-1AE0-DAEA9A499808
> > +  MODULE_TYPE                    = DXE_DRIVER
> > +  VERSION_STRING                 = 1.0
> > +
> > +  ENTRY_POINT                    = InitializeLogo
> > +#
> > +#  This flag specifies whether HII resource section is generated into PE
> image.
> > +#
> > +  UEFI_HII_RESOURCE_SECTION      = TRUE
> > +
> > +#
> > +# The following information is for reference only and not required by
> > +the build
> > tools.
> > +#
> > +#  VALID_ARCHITECTURES           = IA32 X64
> > +#
> > +
> > +[Sources]
> > +  S3Logo.bmp
> > +  Logo.c
> > +  S3Logo.idf
> > +
> > +[Packages]
> > +  AmdPlatformPkg/AmdPlatformPkg.dec
> > +  MdePkg/MdePkg.dec
> > +  MdeModulePkg/MdeModulePkg.dec
> > +
> > +[LibraryClasses]
> > +  BootLogoLib
> > +  DebugLib
> > +  PcdLib
> > +  UefiBootServicesTableLib
> > +  UefiDriverEntryPoint
> > +
> > +[Protocols]
> > +  gEfiHiiDatabaseProtocolGuid        ## CONSUMES
> > +  gEfiHiiImageExProtocolGuid         ## CONSUMES
> > +  gEfiHiiPackageListProtocolGuid     ## PRODUCES CONSUMES
> > +  gEdkiiPlatformLogoProtocolGuid     ## PRODUCES
> > +
> > +[Pcd]
> > +  gAmdPlatformPkgTokenSpaceGuid.PcdAmdDisplayLogoEventGuid
> > +
> > +[Depex]
> > +  gEfiHiiDatabaseProtocolGuid AND
> > +  gEfiHiiImageExProtocolGuid
> > --
> > 2.31.1
>
>



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114683): https://edk2.groups.io/g/devel/message/114683
Mute This Topic: https://groups.io/mt/103975435/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2024-01-29 10:59 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-26 13:10 [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
2024-01-26 13:10 ` [edk2-devel] [PATCH V3 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
2024-01-29 10:37   ` Chang, Abner via groups.io
2024-01-29 10:42     ` Zhai, MingXin (Duke) via groups.io
2024-01-29 10:59       ` Chang, Abner via groups.io
2024-01-26 13:10 ` [edk2-devel] [PATCH V3 02/32] AMD/VanGoghBoard: Check in ACPI tables Zhai, MingXin (Duke) via groups.io
2024-01-26 13:10 ` [edk2-devel] [PATCH V3 03/32] AMD/VanGoghBoard: Check in Capsule update Zhai, MingXin (Duke) via groups.io
2024-01-26 13:10 ` [edk2-devel] [PATCH V3 04/32] AMD/VanGoghBoard: Check in AgesaPublicPkg Zhai, MingXin (Duke) via groups.io
2024-01-26 13:10 ` [edk2-devel] [PATCH V3 05/32] AMD/VanGoghBoard: Check in PlatformSecLib Zhai, MingXin (Duke) via groups.io
2024-01-26 13:10 ` [edk2-devel] [PATCH V3 06/32] AMD/VanGoghBoard: Check in AmdIdsExtLib Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 07/32] AMD/VanGoghBoard: Check in PciPlatform Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 08/32] AMD/VanGoghBoard: Check in UDKFlashUpdate Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 09/32] AMD/VanGoghBoard: Check in Flash_AB Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 10/32] AMD/VanGoghBoard: Check in FlashUpdate Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 11/32] AMD/VanGoghBoard: Check in FvbServices Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 12/32] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 14/32] AMD/VanGoghBoard: Check in SmbiosLib Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 15/32] AMD/VanGoghBoard: Check in SpiFlashDeviceLib Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 16/32] AMD/VanGoghBoard: Check in BaseTscTimerLib Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 17/32] AMD/VanGoghBoard: Check in Smm access module Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 18/32] AMD/VanGoghBoard: Check in PciHostBridge module Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 19/32] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 20/32] AMD/VanGoghBoard: Check in FTPM module Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 21/32] AMD/VanGoghBoard: Check in SignedCapsule Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 22/32] AMD/VanGoghBoard: Check in Vtf0 Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 23/32] AMD/VanGoghBoard: Check in AcpiPlatform Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 24/32] AMD/VanGoghBoard: Check in FchSpi module Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 25/32] AMD/VanGoghBoard: Check in PlatformInitPei module Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 26/32] AMD/VanGoghBoard: Check in Smbios platform dxe drivers Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 29/32] AMD/VanGoghBoard: Check in SmramSaveState module Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 30/32] AMD/VanGoghBoard: Check in EDK2 override files Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module Zhai, MingXin (Duke) via groups.io
2024-01-26 13:11 ` [edk2-devel] [PATCH V3 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script Zhai, MingXin (Duke) via groups.io
2024-01-26 13:30 ` [edk2-devel] [PATCH V3 00/32] Introduce AMD Vangogh platform reference code Chang, Abner via groups.io
2024-01-29  3:23   ` Zhai, MingXin (Duke) via groups.io
2024-01-29  4:46     ` Chang, Abner via groups.io

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox