* [edk2-devel] [PATCH V2 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 9:19 ` Chang, Abner via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114494): https://edk2.groups.io/g/devel/message/114494
Mute This Topic: https://groups.io/mt/103971390/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
* Re: [edk2-devel] [PATCH V2 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 9:19 ` Chang, Abner via groups.io
0 siblings, 0 replies; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-26 9:19 UTC (permalink / raw)
To: Zhai, MingXin (Duke), devel@edk2.groups.io; +Cc: Yao, Ken, Fu, Igniculus
[AMD Official Use Only - General]
> -----Original Message-----
> From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> Sent: Friday, January 26, 2024 2:00 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 V2 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
> +
> +**/
Please put AMD copyright under Intel's.
Thanks
Abner
> +#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 (#114565): https://edk2.groups.io/g/devel/message/114565
Mute This Topic: https://groups.io/mt/103971390/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 V2 02/32] AMD/VanGoghBoard: Check in ACPI tables
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114496): https://edk2.groups.io/g/devel/message/114496
Mute This Topic: https://groups.io/mt/103971393/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 V2 03/32] AMD/VanGoghBoard: Check in Capsule update
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 01/32] AMD/AmdPlatformPkg: Check in AMD S3 logo Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 02/32] AMD/VanGoghBoard: Check in ACPI tables Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 04/32] AMD/VanGoghBoard: Check in AgesaPublic pkg 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 6:00 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 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 | 122 ++
.../CapsuleRuntimeDxe/CapsuleService.c | 461 +++++++
.../CapsuleRuntimeDxe/CapsuleService.h | 73 ++
15 files changed, 3729 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..584adfaee9
--- /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..c99dd4cd47
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
@@ -0,0 +1,122 @@
+## @file
+# Capsule Runtime DXE Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @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) 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..fc6d831663
--- /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 (#114497): https://edk2.groups.io/g/devel/message/114497
Mute This Topic: https://groups.io/mt/103971394/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 V2 04/32] AMD/VanGoghBoard: Check in AgesaPublic pkg
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (2 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 03/32] AMD/VanGoghBoard: Check in Capsule update Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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:
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..f36378dae1
--- /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..7163448844
--- /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..40ccd5e12a
--- /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..aa94ed373c
--- /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..f595d57366
--- /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..73838b5934
--- /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..51c2652614
--- /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..662aaf9736
--- /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..b6463512b6
--- /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 (#114495): https://edk2.groups.io/g/devel/message/114495
Mute This Topic: https://groups.io/mt/103971392/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 V2 05/32]AMD/VanGoghBoard: Check in PlatformSecLib
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (3 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 04/32] AMD/VanGoghBoard: Check in AgesaPublic pkg Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114498): https://edk2.groups.io/g/devel/message/114498
Mute This Topic: https://groups.io/mt/103971395/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 V2 06/32] AMD/VanGoghBoard: Check in AmdIdsExtLib
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (4 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 05/32]AMD/VanGoghBoard: Check in PlatformSecLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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:
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 (#114499): https://edk2.groups.io/g/devel/message/114499
Mute This Topic: https://groups.io/mt/103971396/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 V2 07/32] AMD/VanGoghBoard: Check in PciPlatform
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (5 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 06/32] AMD/VanGoghBoard: Check in AmdIdsExtLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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:
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 ++++++
| 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..e844932cc0
--- /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
--git a/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/CommonHeader.h b/Platform/AMD/VanGoghBoard/ChachaniBoardPkg/PciPlatform/CommonHeader.h
new file mode 100644
index 0000000000..f4e6461206
--- /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 (#114500): https://edk2.groups.io/g/devel/message/114500
Mute This Topic: https://groups.io/mt/103971397/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 V2 08/32] AMD/VanGoghBoard: Check in UDKFlashUpdate
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (6 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 07/32] AMD/VanGoghBoard: Check in PciPlatform Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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:
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..fe4d99e82c
--- /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 (#114501): https://edk2.groups.io/g/devel/message/114501
Mute This Topic: https://groups.io/mt/103971398/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 V2 09/32] AMD/VanGoghBoard: Check in Flash_AB
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (7 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 08/32] AMD/VanGoghBoard: Check in UDKFlashUpdate Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114502): https://edk2.groups.io/g/devel/message/114502
Mute This Topic: https://groups.io/mt/103971399/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 V2 10/32] AMD/VanGoghBoard: Check in FlashUpdate
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (8 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 09/32] AMD/VanGoghBoard: Check in Flash_AB Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 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..616035b82d
--- /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..14bd37ed2e
--- /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..08caf4257b
--- /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 (#114503): https://edk2.groups.io/g/devel/message/114503
Mute This Topic: https://groups.io/mt/103971400/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 V2 11/32] AMD/VanGoghBoard: Check in FvbServices
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (9 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 10/32] AMD/VanGoghBoard: Check in FlashUpdate Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114504): https://edk2.groups.io/g/devel/message/114504
Mute This Topic: https://groups.io/mt/103971401/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 V2 12/32] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (10 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 11/32] AMD/VanGoghBoard: Check in FvbServices Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114505): https://edk2.groups.io/g/devel/message/114505
Mute This Topic: https://groups.io/mt/103971402/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 V2 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (11 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 12/32] AMD/VanGoghBoard: Check in AMD BaseSerialPortLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 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 | 64 +++
6 files changed, 1396 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..a6ec077f05
--- /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..c7c3591479
--- /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..832669bbf4
--- /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..3689a3bae3
--- /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..53d65339aa
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
@@ -0,0 +1,64 @@
+## @file
+# Platform Flash AccessLib
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+# Platform Flash Access library.
+#
+# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = 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 (#114506): https://edk2.groups.io/g/devel/message/114506
Mute This Topic: https://groups.io/mt/103971403/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 V2 14/32] AMD/VanGoghBoard: Check in SmbiosLib
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (12 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 13/32] AMD/VanGoghBoard: Check in PlatformFlashAccessLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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:
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..314f0448fd
--- /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 (#114508): https://edk2.groups.io/g/devel/message/114508
Mute This Topic: https://groups.io/mt/103971405/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 V2 15/32] AMD/VanGoghBoard: Check in SpiFlashDeviceLib
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (13 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 14/32] AMD/VanGoghBoard: Check in SmbiosLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114507): https://edk2.groups.io/g/devel/message/114507
Mute This Topic: https://groups.io/mt/103971404/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 V2 16/32] AMD/VanGoghBoard: Check in BaseTscTimerLib
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (14 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 15/32] AMD/VanGoghBoard: Check in SpiFlashDeviceLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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:
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 | 62 +++++
.../Library/TscTimerLib/PeiTscTimerLib.c | 53 ++++
.../Library/TscTimerLib/PeiTscTimerLib.inf | 56 ++++
.../Library/TscTimerLib/TscTimerLibInternal.h | 53 ++++
.../Library/TscTimerLib/TscTimerLibShare.c | 255 ++++++++++++++++++
8 files changed, 625 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..c1a5d39ab1
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/DxeTscTimerLib.inf
@@ -0,0 +1,62 @@
+## @file
+# DxeTscTimerLib
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @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) 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..e1c3bb695c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Library/TscTimerLib/PeiTscTimerLib.inf
@@ -0,0 +1,56 @@
+## @file
+# PeiTscTimerLib
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @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) 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..cd4fc9db14
--- /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 (#114509): https://edk2.groups.io/g/devel/message/114509
Mute This Topic: https://groups.io/mt/103971406/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 V2 17/32] AMD/VanGoghBoard: Check in Smm access module
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (15 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 16/32] AMD/VanGoghBoard: Check in BaseTscTimerLib Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114510): https://edk2.groups.io/g/devel/message/114510
Mute This Topic: https://groups.io/mt/103971407/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 V2 18/32] AMD/VanGoghBoard: Check in PciHostBridge module
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (16 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 17/32] AMD/VanGoghBoard: Check in Smm access module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 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 +
| 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..41d6a89ce3
--- /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..b13c8c1612
--- /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 (#114512): https://edk2.groups.io/g/devel/message/114512
Mute This Topic: https://groups.io/mt/103971409/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 V2 19/32] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (17 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 18/32] AMD/VanGoghBoard: Check in PciHostBridge module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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:
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 +++
| 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..159bebf309
--- /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;
+}
--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 (#114511): https://edk2.groups.io/g/devel/message/114511
Mute This Topic: https://groups.io/mt/103971408/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 V2 20/32] AMD/VanGoghBoard: Check in FTPM module
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (18 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 19/32] AMD/VanGoghBoard: Check in PcatRealTimeClockRuntimeDxe module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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:
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 | 35 +
| 15 +
.../Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl | 408 ++++++
.../Tcg/Tcg2Config/Tcg2ConfigNvData.h | 124 ++
.../Tcg/Tcg2Config/Tcg2ConfigPei.inf | 77 +
.../Tcg/Tcg2Config/Tcg2ConfigPei.uni | 14 +
| 15 +
.../Tcg/Tcg2Config/Tcg2ConfigPeim.c | 148 ++
.../SecurityPkg/Tcg/Tcg2Config/TpmDetection.c | 99 ++
25 files changed, 4235 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..b1fda8c6b4
--- /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..17618d7fe5
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tcg2Smm.uni
@@ -0,0 +1,35 @@
+// *****************************************************************************
+//
+// * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+// * SPDX-License-Identifier: BSD-2-Clause-Patent
+// *****************************************************************************
+// */
+
+// /** @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.
+//
+// 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) 2015, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#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."
+
--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..297805b840
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SecurityPkg/Tcg/AmdFtpm/FtpmTcg2Smm/Tpm.asl
@@ -0,0 +1,408 @@
+/*****************************************************************************
+ *
+ * Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ ******************************************************************************
+ */
+
+/** @file
+ The TPM2 definition block in ACPI table for TCG2 physical presence
+ and MemoryClear.
+
+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>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+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..86b9362d9f
--- /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."
+
--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 (#114513): https://edk2.groups.io/g/devel/message/114513
Mute This Topic: https://groups.io/mt/103971410/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 V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (19 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 20/32] AMD/VanGoghBoard: Check in FTPM module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 9:28 ` Chang, Abner via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 22/32] AMD/VanGoghBoard: Check in Vtf0 Zhai, MingXin (Duke) via groups.io
` (11 subsequent siblings)
32 siblings, 1 reply; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 6:00 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 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 | 231 +++
.../SystemFirmwareCommonDxe.c | 371 +++++
.../SystemFirmwareUpdate/SystemFirmwareDxe.h | 421 +++++
.../SystemFirmwareUpdateDxe.c | 1426 +++++++++++++++++
.../SystemFirmwareUpdateDxe.inf | 91 ++
.../SystemFirmwareUpdateDxe.uni | 15 +
| 15 +
8 files changed, 2823 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..b57586a267
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigProfile.c
@@ -0,0 +1,231 @@
+/** @file
+ Implements ParseConfigProfile.c
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/** @file
+ Parse the INI configuration file and pass the information to the update driver
+ so that the driver can perform update accordingly.
+
+ Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The
+ full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "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..b1aab4c41e
--- /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..aff752007d
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
@@ -0,0 +1,91 @@
+## @file
+# System Firmware Update Dxe
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+# SystemFirmware FMP update driver.
+#
+# Produce FMP instance to update system firmware.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = 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."
--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 (#114514): https://edk2.groups.io/g/devel/message/114514
Mute This Topic: https://groups.io/mt/103971411/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
* Re: [edk2-devel] [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 9:28 ` Chang, Abner via groups.io
0 siblings, 0 replies; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-26 9:28 UTC (permalink / raw)
To: Zhai, MingXin (Duke), devel@edk2.groups.io; +Cc: Xing, Eric, Fu, Igniculus
[AMD Official Use Only - General]
> -----Original Message-----
> From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> Sent: Friday, January 26, 2024 2:01 PM
> To: devel@edk2.groups.io
> Cc: Xing, Eric <Eric.Xing@amd.com>; Zhai, MingXin (Duke)
> <duke.zhai@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>; Chang,
> Abner <Abner.Chang@amd.com>
> Subject: [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule
>
> 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 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 | 231 +++
> .../SystemFirmwareCommonDxe.c | 371 +++++
> .../SystemFirmwareUpdate/SystemFirmwareDxe.h | 421 +++++
> .../SystemFirmwareUpdateDxe.c | 1426 +++++++++++++++++
> .../SystemFirmwareUpdateDxe.inf | 91 ++
> .../SystemFirmwareUpdateDxe.uni | 15 +
> .../SystemFirmwareUpdateDxeExtra.uni | 15 +
> 8 files changed, 2823 insertions(+)
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/Ge
> nFds/Capsule.py
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/ParseConfigProfile.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareCommonDxe.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareDxe.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/S
> ystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
>
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/G
> enFds/Capsule.py
> b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/G
> enFds/Capsule.py
> new file mode 100644
> index 0000000000..0ec0b3ca43
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/G
> enFds/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/Universa
> l/SystemFirmwareUpdate/ParseConfigProfile.c
> new file mode 100644
> index 0000000000..b57586a267
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/ParseConfigProfile.c
> @@ -0,0 +1,231 @@
> +/** @file
> + Implements ParseConfigProfile.c
> +
> + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
Please put AMD copy right under Intel's.
Thanks
Abner
> +
> +/** @file
> + Parse the INI configuration file and pass the information to the update driver
> + so that the driver can perform update accordingly.
> +
> + Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
> +
> + This program and the accompanying materials
> + are licensed and made available under the terms and conditions
> + of the BSD License which accompanies this distribution. The
> + full text of the license may be found at
> + http://opensource.org/licenses/bsd-license.php
> +
> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include "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/Universa
> l/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c
> new file mode 100644
> index 0000000000..05a36162d3
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/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/Universa
> l/SystemFirmwareUpdate/SystemFirmwareDxe.h
> new file mode 100644
> index 0000000000..b1aab4c41e
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/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/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c
> new file mode 100644
> index 0000000000..894d363de0
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/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/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
> new file mode 100644
> index 0000000000..aff752007d
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf
> @@ -0,0 +1,91 @@
> +## @file
> +# System Firmware Update Dxe
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +## @file
> +# SystemFirmware FMP update driver.
> +#
> +# Produce FMP instance to update system firmware.
> +#
> +# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +# This program and the accompanying materials
> +# are licensed and made available under the terms and conditions of the BSD
> License
> +# which accompanies this distribution. The full text of the license may be
> found at
> +# http://opensource.org/licenses/bsd-license.php
> +#
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = 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.PcdEdkiiSystemFirmwareImageDescript
> or ## 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/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni
> new file mode 100644
> index 0000000000..e6bd18b249
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/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/Universa
> l/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni
> new file mode 100644
> index 0000000000..c549f017a4
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universa
> l/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 (#114566): https://edk2.groups.io/g/devel/message/114566
Mute This Topic: https://groups.io/mt/103971411/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 V2 22/32] AMD/VanGoghBoard: Check in Vtf0
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (20 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 21/32] AMD/VanGoghBoard: Check in SignedCapsule Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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
| 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 (#114515): https://edk2.groups.io/g/devel/message/114515
Mute This Topic: https://groups.io/mt/103971412/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 V2 23/32] AMD/VanGoghBoard: Check in AcpiPlatform
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (21 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 22/32] AMD/VanGoghBoard: Check in Vtf0 Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 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 +++
| 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
--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..9abab0f9e2
--- /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 (#114516): https://edk2.groups.io/g/devel/message/114516
Mute This Topic: https://groups.io/mt/103971413/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 V2 24/32] AMD/VanGoghBoard: Check in FchSpi module
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (22 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 23/32] AMD/VanGoghBoard: Check in AcpiPlatform Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 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..1dd57c6f52
--- /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..47dbee9391
--- /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..b3b23842a3
--- /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 (#114517): https://edk2.groups.io/g/devel/message/114517
Mute This Topic: https://groups.io/mt/103971415/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 V2 25/32] AMD/VanGoghBoard: Check in PlatformInitPei module
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (23 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 24/32] AMD/VanGoghBoard: Check in FchSpi module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114518): https://edk2.groups.io/g/devel/message/114518
Mute This Topic: https://groups.io/mt/103971418/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 V2 26/32] AMD/VanGoghBoard: Check in Smbios platform dxe drivers
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (24 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 25/32] AMD/VanGoghBoard: Check in PlatformInitPei module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 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 | 53 +++
.../Universal/PlatformSmbiosDxe/SmbiosTable.c | 382 ++++++++++++++++++
3 files changed, 510 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..e16a448d7a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Universal/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
@@ -0,0 +1,53 @@
+## @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 (#114519): https://edk2.groups.io/g/devel/message/114519
Mute This Topic: https://groups.io/mt/103971419/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 V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (25 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 26/32] AMD/VanGoghBoard: Check in Smbios platform dxe drivers Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 9:34 ` Chang, Abner via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module Zhai, MingXin (Duke) via groups.io
` (5 subsequent siblings)
32 siblings, 1 reply; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 6:00 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 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 | 167 ++
.../FspWrapperNotifyDxe/FspWrapperNotifyDxe.c | 676 ++++++++
.../FspWrapperNotifyDxe.inf | 82 +
.../FspWrapperNotifyDxe/LoadBelow4G.c | 147 ++
.../FspmWrapperPeim/FspmWrapperPeim.c | 478 ++++++
.../FspmWrapperPeim/FspmWrapperPeim.inf | 99 ++
.../FspsMultiPhaseSiInitDxe.c | 206 +++
.../FspsMultiPhaseSiInitDxe.inf | 81 +
.../FspsMultiPhaseSiInitDxe/LoadBelow4G.c | 148 ++
.../FspsWrapperPeim/FspsWrapperPeim.c | 632 ++++++++
.../FspsWrapperPeim/FspsWrapperPeim.inf | 98 ++
.../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 | 73 +
.../BaseFspWrapperApiLib/FspWrapperApiLib.c | 235 +++
.../IA32/DispatchExecute.c | 71 +
.../X64/DispatchExecute.c | 167 ++
.../BaseFspWrapperApiLib/X64/Thunk64To32.nasm | 252 +++
.../BaseFspWrapperApiTestLibNull.inf | 56 +
.../FspWrapperApiTestNull.c | 60 +
.../BaseFspWrapperPlatformLibSample.inf | 79 +
.../FspWrapperPlatformLibSample.c | 347 ++++
...aseFspWrapperPlatformMultiPhaseLibNull.inf | 45 +
.../FspWrapperPlatformMultiPhaseLibNull.c | 51 +
.../DxeFspWrapperMultiPhaseProcessLib.c | 531 ++++++
.../DxeFspWrapperMultiPhaseProcessLib.inf | 87 +
.../FspWrapperMultiPhaseProcessLib.inf | 56 +
.../PeiFspWrapperMultiPhaseProcessLib.c | 385 +++++
.../FspWrapperApiTest.c | 85 +
.../PeiFspWrapperApiTestLib.inf | 59 +
| 91 ++
.../FspWrapperHobProcessLibSample.c | 1439 +++++++++++++++++
.../MemoryInstall.h | 171 ++
.../PeiFspWrapperHobProcessLibSample.inf | 128 ++
.../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, 10222 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..25327755e6
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2WrapperPkg.dec
@@ -0,0 +1,167 @@
+## @file
+# EDK II Fsp2WrapperPkg.dec file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+## @file
+# Provides drivers and definitions to support fsp in EDKII bios.
+#
+# 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..9ec6de6a13
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapperNotifyDxe/FspWrapperNotifyDxe.inf
@@ -0,0 +1,82 @@
+## @file
+# FSP-S wrapper Notify DXE Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+# FSP DXE Module
+#
+# This driver will register two callbacks to call fsp's notifies.
+#
+# 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..ced1873a44
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
@@ -0,0 +1,99 @@
+## @file
+# FSP-M wrapper PEI Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @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) 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..7eefe691cf
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiPhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
@@ -0,0 +1,81 @@
+## @file
+# FSP DXE Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+# FSP DXE Module
+#
+# This driver will register two callbacks to call fsp's notifies.
+#
+# 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..e43a8c941f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
@@ -0,0 +1,98 @@
+## @file
+# FSP-S wrapper PEI Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @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) 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..a4827a0068
--- /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..ed9a6c79a3
--- /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..c1fb89c63d
--- /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..604efefa7d
--- /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..7172544b8a
--- /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..073c6e1d0e
--- /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..c4e785e41e
--- /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..8c0c244e43
--- /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..89cff5ea4a
--- /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..529bc31145
--- /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..9be1b17b29
--- /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..23d46ea1f1
--- /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..7bb32290cb
--- /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..e41d17d67c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
@@ -0,0 +1,73 @@
+## @file
+# FSP API related function INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+# Provide FSP API related function.
+#
+# 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..4d40f86b3a
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
@@ -0,0 +1,56 @@
+## @file
+# FSP wrapper API test related function INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+### @file
+# Provide FSP wrapper API test related function.
+#
+# 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..1f66593a52
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
@@ -0,0 +1,79 @@
+## @file
+# FSP wrapper platform related function INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+# Sample to provide FSP wrapper platform related function.
+#
+# 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..f9f1a12c2f
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/BaseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPhaseLibNull.inf
@@ -0,0 +1,45 @@
+## @file
+# FSP Wrapper to handle platform specific actions for
+# FSP MultiPhase (SeparatePhase) Initialization.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+# FSP Wrapper to handle platform specific actions for
+# FSP MultiPhase (SeparatePhase) Initialization.
+#
+# 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..21912fba99
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/DxeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.inf
@@ -0,0 +1,87 @@
+## @file
+# FSP wrapper DXE FSP MultiPhase (SeparatePhase) INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @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..6f681780e3
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/FspWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
@@ -0,0 +1,56 @@
+## @file
+# FSP wrapper PEI FSP MultiPhase (SeparatePhase) INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+# FSP wrapper to handle FSP MultiPhase (SeparatePhase) Initialization.
+#
+# 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..5b378c6c55
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
@@ -0,0 +1,59 @@
+## @file
+# FSP wrapper FSP-M wrapper API test INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+### @file
+# Provide FSP-M wrapper API test related function.
+#
+# 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
--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..d512feaa5b
--- /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..6fdfb8e34c
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
@@ -0,0 +1,128 @@
+## @file
+# FSP wrapper hob process INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @file
+# Sample to provide FSP wrapper hob process related function.
+#
+# 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..0bb612ea87
--- /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 (#114523): https://edk2.groups.io/g/devel/message/114523
Mute This Topic: https://groups.io/mt/103971425/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
* Re: [edk2-devel] [PATCH V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 9:34 ` Chang, Abner via groups.io
2024-01-26 9:36 ` Chang, Abner via groups.io
0 siblings, 1 reply; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-26 9:34 UTC (permalink / raw)
To: Zhai, MingXin (Duke), devel@edk2.groups.io; +Cc: Xing, Eric, Fu, Igniculus
[AMD Official Use Only - General]
> -----Original Message-----
> From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> Sent: Friday, January 26, 2024 2:01 PM
> To: devel@edk2.groups.io
> Cc: Xing, Eric <Eric.Xing@amd.com>; Zhai, MingXin (Duke)
> <duke.zhai@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>; Chang,
> Abner <Abner.Chang@amd.com>
> Subject: [PATCH V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg
>
> 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 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 | 167 ++
> .../FspWrapperNotifyDxe/FspWrapperNotifyDxe.c | 676 ++++++++
> .../FspWrapperNotifyDxe.inf | 82 +
> .../FspWrapperNotifyDxe/LoadBelow4G.c | 147 ++
> .../FspmWrapperPeim/FspmWrapperPeim.c | 478 ++++++
> .../FspmWrapperPeim/FspmWrapperPeim.inf | 99 ++
> .../FspsMultiPhaseSiInitDxe.c | 206 +++
> .../FspsMultiPhaseSiInitDxe.inf | 81 +
> .../FspsMultiPhaseSiInitDxe/LoadBelow4G.c | 148 ++
> .../FspsWrapperPeim/FspsWrapperPeim.c | 632 ++++++++
> .../FspsWrapperPeim/FspsWrapperPeim.inf | 98 ++
> .../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 | 73 +
> .../BaseFspWrapperApiLib/FspWrapperApiLib.c | 235 +++
> .../IA32/DispatchExecute.c | 71 +
> .../X64/DispatchExecute.c | 167 ++
> .../BaseFspWrapperApiLib/X64/Thunk64To32.nasm | 252 +++
> .../BaseFspWrapperApiTestLibNull.inf | 56 +
> .../FspWrapperApiTestNull.c | 60 +
> .../BaseFspWrapperPlatformLibSample.inf | 79 +
> .../FspWrapperPlatformLibSample.c | 347 ++++
> ...aseFspWrapperPlatformMultiPhaseLibNull.inf | 45 +
> .../FspWrapperPlatformMultiPhaseLibNull.c | 51 +
> .../DxeFspWrapperMultiPhaseProcessLib.c | 531 ++++++
> .../DxeFspWrapperMultiPhaseProcessLib.inf | 87 +
> .../FspWrapperMultiPhaseProcessLib.inf | 56 +
> .../PeiFspWrapperMultiPhaseProcessLib.c | 385 +++++
> .../FspWrapperApiTest.c | 85 +
> .../PeiFspWrapperApiTestLib.inf | 59 +
> .../CommonHeader.h | 91 ++
> .../FspWrapperHobProcessLibSample.c | 1439 +++++++++++++++++
> .../MemoryInstall.h | 171 ++
> .../PeiFspWrapperHobProcessLibSample.inf | 128 ++
> .../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, 10222 insertions(+)
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Release
> _Notes.txt
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2Wrapp
> erPkg.dec
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapper
> NotifyDxe/FspWrapperNotifyDxe.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapper
> NotifyDxe/FspWrapperNotifyDxe.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapper
> NotifyDxe/LoadBelow4G.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapp
> erPeim/FspmWrapperPeim.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapp
> erPeim/FspmWrapperPeim.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiP
> haseSiInitDxe/FspsMultiPhaseSiInitDxe.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiP
> haseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiP
> haseSiInitDxe/LoadBelow4G.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapp
> erPeim/FspsWrapperPeim.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapp
> erPeim/FspsWrapperPeim.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> ExportedInterfaceHob.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> MemoryRegionHob.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> SmmDataExchangeBuffer.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> Upd.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> mUpd.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> sUpd.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> tUpd.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> ary/FspMeasurementLib.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> ary/FspWrapperApiLib.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> ary/FspWrapperApiTestLib.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> ary/FspWrapperHobProcessLib.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> ary/FspWrapperMultiPhaseProcessLib.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> ary/FspWrapperPlatformLib.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> ary/FspWrapperPlatformMultiPhaseLib.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Mul
> tiPhaseSiPhases.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/Bas
> eFspMeasurementLib/BaseFspMeasurementLib.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspMeasurementLib/FspMeasurementLib.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperApiLib/BaseFspWrapperApiLib.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperApiLib/FspWrapperApiLib.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperApiLib/IA32/DispatchExecute.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperApiLib/X64/DispatchExecute.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperApiLib/X64/Thunk64To32.nasm
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPhase
> LibNull.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> eFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLibN
> ull.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Dxe
> FspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Dxe
> FspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fsp
> WrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fsp
> WrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> spWrapperApiTestLib/FspWrapperApiTest.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> spWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> spWrapperHobProcessLibSample/CommonHeader.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> spWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> spWrapperHobProcessLibSample/MemoryInstall.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> spWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/Fsp.h
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/Ia32/Stack.nasm
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/PlatformInit.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/SecGetPerformance.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/SecPlatformInformation.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/SecRamInitData.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/SecTempRamDone.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/X64/SecEntry.nasm
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> spWrapperPlatformSecLibSample/X64/Stack.nasm
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForF
> spSmmDxe/PrepareForFspSmmDxe.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForF
> spSmmDxe/PrepareForFspSmmDxe.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForF
> spSmmDxeFsp/PrepareForFspSmmDxeFsp.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForF
> spSmmDxeFsp/PrepareForFspSmmDxeFsp.inf
>
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Relea
> se_Notes.txt
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Rele
> ase_Notes.txt
> new file mode 100644
> index 0000000000..92e8f7a43b
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Rele
> ase_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/Fsp2Wra
> pperPkg.dec
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2Wra
> pperPkg.dec
> new file mode 100644
> index 0000000000..25327755e6
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2Wra
> pperPkg.dec
> @@ -0,0 +1,167 @@
> +## @file
> +# EDK II Fsp2WrapperPkg.dec file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
Please put AMD copy right under Intel's.
> +## @file
> +# Provides drivers and definitions to support fsp in EDKII bios.
> +#
> +# 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/FspWrapperMultiPhasePr
> ocessLib.h
> +
> + ## @libraryclass Provide MultiPhase platform actions related functions.
> +
> FspWrapperPlatformMultiPhaseLib|Include/Library/FspWrapperPlatformMul
> tiPhaseLib.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|UI
> NT32|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|UINT
> 32|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|0x
> 40000009
> +
> + ## 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|UIN
> T8|0x4000000A
> +
> + #
> + ## These are the base address of FSP-M/S
> + #
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInFlash|0x00000000|U
> INT32|0x00001000
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInFlash|0x00000000|UI
> NT32|0x00001001
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspoPeiBaseAddressInFlash|0x00000000|
> UINT32|0x00001002
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspoDxeBaseAddressInFlash|0x00000000
> |UINT32|0x00001003
> +
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInMemory|0x0000000
> 0|UINT32|0x00002000
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInMemory|0x00000000
> |UINT32|0x00002001
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspoPeiBaseAddressInMemory|0x000000
> 00|UINT32|0x00002002
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspoDxeBaseAddressInMemory|0x00000
> 000|UINT32|0x00002003
> +
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspmRegionSize|0x00000000|UINT32|0x
> 00003000
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspsRegionSize|0x00000000|UINT32|0x
> 00003001
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspoPeiRegionSize|0x00000000|UINT32|
> 0x00003002
> +
> gFsp2WrapperTokenSpaceGuid.PcdFspoDxeRegionSize|0x00000000|UINT32
> |0x00003003
> +
> +
> gFsp2WrapperTokenSpaceGuid.FspoPeiWorkaroundShadowCopyAddress|0x
> 09E00000|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|0x0000000
> 0|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/FspWrap
> perNotifyDxe/FspWrapperNotifyDxe.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> perNotifyDxe/FspWrapperNotifyDxe.c
> new file mode 100644
> index 0000000000..0c997b40d0
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> perNotifyDxe/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/FspWrap
> perNotifyDxe/FspWrapperNotifyDxe.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> perNotifyDxe/FspWrapperNotifyDxe.inf
> new file mode 100644
> index 0000000000..9ec6de6a13
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> perNotifyDxe/FspWrapperNotifyDxe.inf
> @@ -0,0 +1,82 @@
> +## @file
> +# FSP-S wrapper Notify DXE Module INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
Please put AMD copy right under Intel's.
> +
> +## @file
> +# FSP DXE Module
> +#
> +# This driver will register two callbacks to call fsp's notifies.
> +#
> +# 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/FspWrap
> perNotifyDxe/LoadBelow4G.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> perNotifyDxe/LoadBelow4G.c
> new file mode 100644
> index 0000000000..9a49d3b492
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> perNotifyDxe/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))(NewImage
> Handle, 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/FspmWra
> pperPeim/FspmWrapperPeim.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWra
> pperPeim/FspmWrapperPeim.c
> new file mode 100644
> index 0000000000..fc5a339e8b
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWra
> pperPeim/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/FspmWra
> pperPeim/FspmWrapperPeim.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWra
> pperPeim/FspmWrapperPeim.inf
> new file mode 100644
> index 0000000000..ced1873a44
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWra
> pperPeim/FspmWrapperPeim.inf
> @@ -0,0 +1,99 @@
> +## @file
> +# FSP-M wrapper PEI Module INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
Please put AMD copy right under Intel's.
> +
> +## @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) 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/FspsMulti
> PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.c
> new file mode 100644
> index 0000000000..bb5e12cba9
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> PhaseSiInitDxe/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/FspsMulti
> PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
> new file mode 100644
> index 0000000000..7eefe691cf
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
> @@ -0,0 +1,81 @@
> +## @file
> +# FSP DXE Module INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
Please put AMD copy right under Intel's.
> +## @file
> +# FSP DXE Module
> +#
> +# This driver will register two callbacks to call fsp's notifies.
> +#
> +# 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.PcdAmdFspSetupTableInitNeedsRe
> set
> +
> +[Depex]
> + TRUE
> diff --git
> a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> PhaseSiInitDxe/LoadBelow4G.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> PhaseSiInitDxe/LoadBelow4G.c
> new file mode 100644
> index 0000000000..ae05556cc9
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> PhaseSiInitDxe/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))(NewImage
> Handle, 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/FspsWrap
> perPeim/FspsWrapperPeim.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrap
> perPeim/FspsWrapperPeim.c
> new file mode 100644
> index 0000000000..e6a589bcb5
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrap
> perPeim/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/FspsWrap
> perPeim/FspsWrapperPeim.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrap
> perPeim/FspsWrapperPeim.inf
> new file mode 100644
> index 0000000000..e43a8c941f
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrap
> perPeim/FspsWrapperPeim.inf
> @@ -0,0 +1,98 @@
> +## @file
> +# FSP-S wrapper PEI Module INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +## @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) 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/F
> spExportedInterfaceHob.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spExportedInterfaceHob.h
> new file mode 100644
> index 0000000000..66778b0143
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spExportedInterfaceHob.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/F
> spMemoryRegionHob.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spMemoryRegionHob.h
> new file mode 100644
> index 0000000000..3319cad3bc
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spMemoryRegionHob.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/F
> spSmmDataExchangeBuffer.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spSmmDataExchangeBuffer.h
> new file mode 100644
> index 0000000000..1eaa187bb8
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spSmmDataExchangeBuffer.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/F
> spUpd.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spUpd.h
> new file mode 100644
> index 0000000000..a4827a0068
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spUpd.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/F
> spmUpd.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spmUpd.h
> new file mode 100644
> index 0000000000..ed9a6c79a3
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spmUpd.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/F
> spsUpd.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spsUpd.h
> new file mode 100644
> index 0000000000..c1fb89c63d
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> spsUpd.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/F
> sptUpd.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> sptUpd.h
> new file mode 100644
> index 0000000000..604efefa7d
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> sptUpd.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/Li
> brary/FspMeasurementLib.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/FspMeasurementLib.h
> new file mode 100644
> index 0000000000..7172544b8a
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/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/Li
> brary/FspWrapperApiLib.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/FspWrapperApiLib.h
> new file mode 100644
> index 0000000000..073c6e1d0e
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/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/Li
> brary/FspWrapperApiTestLib.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/FspWrapperApiTestLib.h
> new file mode 100644
> index 0000000000..c4e785e41e
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/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/Li
> brary/FspWrapperHobProcessLib.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/FspWrapperHobProcessLib.h
> new file mode 100644
> index 0000000000..8c0c244e43
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/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/Li
> brary/FspWrapperMultiPhaseProcessLib.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/FspWrapperMultiPhaseProcessLib.h
> new file mode 100644
> index 0000000000..89cff5ea4a
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/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/Li
> brary/FspWrapperPlatformLib.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/FspWrapperPlatformLib.h
> new file mode 100644
> index 0000000000..529bc31145
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/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/Li
> brary/FspWrapperPlatformMultiPhaseLib.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/FspWrapperPlatformMultiPhaseLib.h
> new file mode 100644
> index 0000000000..8e16ddb719
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> brary/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..9be1b17b29
> --- /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/P
> pi/FspSiliconInitDone.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/P
> pi/FspSiliconInitDone.h
> new file mode 100644
> index 0000000000..23d46ea1f1
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/P
> pi/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/P
> pi/TopOfTemporaryRam.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/P
> pi/TopOfTemporaryRam.h
> new file mode 100644
> index 0000000000..7bb32290cb
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/P
> pi/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/B
> aseFspMeasurementLib/BaseFspMeasurementLib.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspMeasurementLib/BaseFspMeasurementLib.inf
> new file mode 100644
> index 0000000000..48eb4991dd
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspMeasurementLib/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/B
> aseFspMeasurementLib/FspMeasurementLib.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspMeasurementLib/FspMeasurementLib.c
> new file mode 100644
> index 0000000000..9a9368bb75
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspMeasurementLib/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/B
> aseFspWrapperApiLib/BaseFspWrapperApiLib.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/BaseFspWrapperApiLib.inf
> new file mode 100644
> index 0000000000..e41d17d67c
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/BaseFspWrapperApiLib.inf
> @@ -0,0 +1,73 @@
> +## @file
> +# FSP API related function INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
Please put AMD copy right under Intel's.
> +
> +## @file
> +# Provide FSP API related function.
> +#
> +# 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/B
> aseFspWrapperApiLib/FspWrapperApiLib.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/FspWrapperApiLib.c
> new file mode 100644
> index 0000000000..80d64f9bd2
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/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/B
> aseFspWrapperApiLib/IA32/DispatchExecute.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/IA32/DispatchExecute.c
> new file mode 100644
> index 0000000000..434eb549a4
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/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/B
> aseFspWrapperApiLib/X64/DispatchExecute.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/X64/DispatchExecute.c
> new file mode 100644
> index 0000000000..3c34806286
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/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/B
> aseFspWrapperApiLib/X64/Thunk64To32.nasm
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/X64/Thunk64To32.nasm
> new file mode 100644
> index 0000000000..f1a14b2446
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiLib/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/B
> aseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
> new file mode 100644
> index 0000000000..4d40f86b3a
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
> @@ -0,0 +1,56 @@
> +## @file
> +# FSP wrapper API test related function INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +### @file
> +# Provide FSP wrapper API test related function.
> +#
> +# 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/B
> aseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
> new file mode 100644
> index 0000000000..19bd3afc29
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperApiTestLibNull/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/B
> aseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
> new file mode 100644
> index 0000000000..1f66593a52
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
> @@ -0,0 +1,79 @@
> +## @file
> +# FSP wrapper platform related function INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +## @file
> +# Sample to provide FSP wrapper platform related function.
> +#
> +# 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/B
> aseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
> new file mode 100644
> index 0000000000..1afcf68f85
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperPlatformLibSample/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/B
> aseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPha
> seLibNull.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPha
> seLibNull.inf
> new file mode 100644
> index 0000000000..f9f1a12c2f
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPha
> seLibNull.inf
> @@ -0,0 +1,45 @@
> +## @file
> +# FSP Wrapper to handle platform specific actions for
> +# FSP MultiPhase (SeparatePhase) Initialization.
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +## @file
> +# FSP Wrapper to handle platform specific actions for
> +# FSP MultiPhase (SeparatePhase) Initialization.
> +#
> +# 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/B
> aseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLi
> bNull.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLi
> bNull.c
> new file mode 100644
> index 0000000000..3a0d0e6088
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> aseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLi
> bNull.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/D
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/D
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
> new file mode 100644
> index 0000000000..cfda44bc71
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/D
> xeFspWrapperMultiPhaseProcessLib/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,PcdS3BootScriptTablePrivateSm
> mDataPtr:%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/D
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.in
> f
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/D
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.in
> f
> new file mode 100644
> index 0000000000..21912fba99
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/D
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.in
> f
> @@ -0,0 +1,87 @@
> +## @file
> +# FSP wrapper DXE FSP MultiPhase (SeparatePhase) INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +## @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.PcdAmdSmmCommunicationAddr
> ess ## 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/Fs
> pWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fs
> pWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
> new file mode 100644
> index 0000000000..6f681780e3
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fs
> pWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
> @@ -0,0 +1,56 @@
> +## @file
> +# FSP wrapper PEI FSP MultiPhase (SeparatePhase) INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +## @file
> +# FSP wrapper to handle FSP MultiPhase (SeparatePhase) Initialization.
> +#
> +# 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/Fs
> pWrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fs
> pWrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
> new file mode 100644
> index 0000000000..e072efbb04
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fs
> pWrapperMultiPhaseProcessLib/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/Pe
> iFspWrapperApiTestLib/FspWrapperApiTest.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperApiTestLib/FspWrapperApiTest.c
> new file mode 100644
> index 0000000000..caffada924
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperApiTestLib/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/Pe
> iFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
> new file mode 100644
> index 0000000000..5b378c6c55
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
> @@ -0,0 +1,59 @@
> +## @file
> +# FSP wrapper FSP-M wrapper API test INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +### @file
> +# Provide FSP-M wrapper API test related function.
> +#
> +# 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/Pe
> iFspWrapperHobProcessLibSample/CommonHeader.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperHobProcessLibSample/CommonHeader.h
> new file mode 100644
> index 0000000000..d512feaa5b
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperHobProcessLibSample/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/Pe
> iFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
> new file mode 100644
> index 0000000000..3100f4635e
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperHobProcessLibSample/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/Pe
> iFspWrapperHobProcessLibSample/MemoryInstall.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperHobProcessLibSample/MemoryInstall.h
> new file mode 100644
> index 0000000000..c9a58aea56
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperHobProcessLibSample/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/Pe
> iFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
> new file mode 100644
> index 0000000000..6fdfb8e34c
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> eiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
> @@ -0,0 +1,128 @@
> +## @file
> +# FSP wrapper hob process INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +## @file
> +# Sample to provide FSP wrapper hob process related function.
> +#
> +# 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.PcdAmdFabricResourceDefaultSize
> Ptr
> +[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/Se
> cFspWrapperPlatformSecLibSample/Fsp.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/Fsp.h
> new file mode 100644
> index 0000000000..0bb612ea87
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
> new file mode 100644
> index 0000000000..54f363e59d
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
> new file mode 100644
> index 0000000000..cf443aa267
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
> new file mode 100644
> index 0000000000..b506212bfa
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/Ia32/Stack.nasm
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/Ia32/Stack.nasm
> new file mode 100644
> index 0000000000..48101131fa
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/PlatformInit.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/PlatformInit.c
> new file mode 100644
> index 0000000000..237aeead51
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.in
> f
> new file mode 100644
> index 0000000000..ac417c8e59
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.in
> f
> @@ -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/Se
> cFspWrapperPlatformSecLibSample/SecGetPerformance.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/SecGetPerformance.c
> new file mode 100644
> index 0000000000..449a2d6e99
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/SecPlatformInformation.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/SecPlatformInformation.c
> new file mode 100644
> index 0000000000..b96f38432e
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/SecRamInitData.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/SecRamInitData.c
> new file mode 100644
> index 0000000000..5e7f051bb6
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/SecTempRamDone.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/SecTempRamDone.c
> new file mode 100644
> index 0000000000..fab488e668
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
> new file mode 100644
> index 0000000000..548474ccbb
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/X64/SecEntry.nasm
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/X64/SecEntry.nasm
> new file mode 100644
> index 0000000000..4025b4157c
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/Se
> cFspWrapperPlatformSecLibSample/X64/Stack.nasm
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/X64/Stack.nasm
> new file mode 100644
> index 0000000000..6feb38ce02
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> ecFspWrapperPlatformSecLibSample/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/PrepareF
> orFspSmmDxe/PrepareForFspSmmDxe.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> orFspSmmDxe/PrepareForFspSmmDxe.c
> new file mode 100644
> index 0000000000..87abe27c09
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> orFspSmmDxe/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/PrepareF
> orFspSmmDxe/PrepareForFspSmmDxe.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> orFspSmmDxe/PrepareForFspSmmDxe.inf
> new file mode 100644
> index 0000000000..03d6c9d668
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> orFspSmmDxe/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/PrepareF
> orFspSmmDxeFsp/PrepareForFspSmmDxeFsp.c
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> orFspSmmDxeFsp/PrepareForFspSmmDxeFsp.c
> new file mode 100644
> index 0000000000..05e5a0bd08
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> orFspSmmDxeFsp/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/PrepareF
> orFspSmmDxeFsp/PrepareForFspSmmDxeFsp.inf
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> orFspSmmDxeFsp/PrepareForFspSmmDxeFsp.inf
> new file mode 100644
> index 0000000000..19dd25b27f
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> orFspSmmDxeFsp/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 (#114567): https://edk2.groups.io/g/devel/message/114567
Mute This Topic: https://groups.io/mt/103971425/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 V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg
2024-01-26 9:34 ` Chang, Abner via groups.io
@ 2024-01-26 9:36 ` Chang, Abner via groups.io
0 siblings, 0 replies; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-26 9:36 UTC (permalink / raw)
To: Zhai, MingXin (Duke), devel@edk2.groups.io; +Cc: Xing, Eric, Fu, Igniculus
[AMD Official Use Only - General]
I didn't go through entire file. Please check it as several copyright are put in the wrong place.
Thanks
Abner
> -----Original Message-----
> From: Chang, Abner
> Sent: Friday, January 26, 2024 5:35 PM
> To: Zhai, MingXin (Duke) <duke.zhai@amd.com>; devel@edk2.groups.io
> Cc: Xing, Eric <Eric.Xing@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>
> Subject: RE: [PATCH V2 27/32] AMD/VanGoghBoard: Check in
> Fsp2WrapperPkg
>
>
>
> > -----Original Message-----
> > From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> > Sent: Friday, January 26, 2024 2:01 PM
> > To: devel@edk2.groups.io
> > Cc: Xing, Eric <Eric.Xing@amd.com>; Zhai, MingXin (Duke)
> > <duke.zhai@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>; Chang,
> > Abner <Abner.Chang@amd.com>
> > Subject: [PATCH V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg
> >
> > 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 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 | 167 ++
> > .../FspWrapperNotifyDxe/FspWrapperNotifyDxe.c | 676 ++++++++
> > .../FspWrapperNotifyDxe.inf | 82 +
> > .../FspWrapperNotifyDxe/LoadBelow4G.c | 147 ++
> > .../FspmWrapperPeim/FspmWrapperPeim.c | 478 ++++++
> > .../FspmWrapperPeim/FspmWrapperPeim.inf | 99 ++
> > .../FspsMultiPhaseSiInitDxe.c | 206 +++
> > .../FspsMultiPhaseSiInitDxe.inf | 81 +
> > .../FspsMultiPhaseSiInitDxe/LoadBelow4G.c | 148 ++
> > .../FspsWrapperPeim/FspsWrapperPeim.c | 632 ++++++++
> > .../FspsWrapperPeim/FspsWrapperPeim.inf | 98 ++
> > .../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 | 73 +
> > .../BaseFspWrapperApiLib/FspWrapperApiLib.c | 235 +++
> > .../IA32/DispatchExecute.c | 71 +
> > .../X64/DispatchExecute.c | 167 ++
> > .../BaseFspWrapperApiLib/X64/Thunk64To32.nasm | 252 +++
> > .../BaseFspWrapperApiTestLibNull.inf | 56 +
> > .../FspWrapperApiTestNull.c | 60 +
> > .../BaseFspWrapperPlatformLibSample.inf | 79 +
> > .../FspWrapperPlatformLibSample.c | 347 ++++
> > ...aseFspWrapperPlatformMultiPhaseLibNull.inf | 45 +
> > .../FspWrapperPlatformMultiPhaseLibNull.c | 51 +
> > .../DxeFspWrapperMultiPhaseProcessLib.c | 531 ++++++
> > .../DxeFspWrapperMultiPhaseProcessLib.inf | 87 +
> > .../FspWrapperMultiPhaseProcessLib.inf | 56 +
> > .../PeiFspWrapperMultiPhaseProcessLib.c | 385 +++++
> > .../FspWrapperApiTest.c | 85 +
> > .../PeiFspWrapperApiTestLib.inf | 59 +
> > .../CommonHeader.h | 91 ++
> > .../FspWrapperHobProcessLibSample.c | 1439 +++++++++++++++++
> > .../MemoryInstall.h | 171 ++
> > .../PeiFspWrapperHobProcessLibSample.inf | 128 ++
> > .../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, 10222 insertions(+)
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Release
> > _Notes.txt
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2Wrapp
> > erPkg.dec
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapper
> > NotifyDxe/FspWrapperNotifyDxe.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapper
> > NotifyDxe/FspWrapperNotifyDxe.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrapper
> > NotifyDxe/LoadBelow4G.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapp
> > erPeim/FspmWrapperPeim.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWrapp
> > erPeim/FspmWrapperPeim.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiP
> > haseSiInitDxe/FspsMultiPhaseSiInitDxe.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiP
> > haseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMultiP
> > haseSiInitDxe/LoadBelow4G.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapp
> > erPeim/FspsWrapperPeim.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrapp
> > erPeim/FspsWrapperPeim.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> > ExportedInterfaceHob.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> > MemoryRegionHob.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> > SmmDataExchangeBuffer.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> > Upd.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> > mUpd.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> > sUpd.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Fsp
> > tUpd.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> > ary/FspMeasurementLib.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> > ary/FspWrapperApiLib.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> > ary/FspWrapperApiTestLib.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> > ary/FspWrapperHobProcessLib.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> > ary/FspWrapperMultiPhaseProcessLib.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> > ary/FspWrapperPlatformLib.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Libr
> > ary/FspWrapperPlatformMultiPhaseLib.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Mul
> > tiPhaseSiPhases.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/Bas
> > eFspMeasurementLib/BaseFspMeasurementLib.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspMeasurementLib/FspMeasurementLib.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspWrapperApiLib/BaseFspWrapperApiLib.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspWrapperApiLib/FspWrapperApiLib.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspWrapperApiLib/IA32/DispatchExecute.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspWrapperApiLib/X64/DispatchExecute.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspWrapperApiLib/X64/Thunk64To32.nasm
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> > eFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> >
> eFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPhase
> > LibNull.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Bas
> >
> eFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLibN
> > ull.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Dxe
> > FspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Dxe
> > FspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fsp
> > WrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fsp
> > WrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> > spWrapperApiTestLib/FspWrapperApiTest.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> > spWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> > spWrapperHobProcessLibSample/CommonHeader.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> > spWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> > spWrapperHobProcessLibSample/MemoryInstall.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/PeiF
> > spWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/Fsp.h
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/Ia32/Stack.nasm
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/PlatformInit.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/SecGetPerformance.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/SecPlatformInformation.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/SecRamInitData.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/SecTempRamDone.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/X64/SecEntry.nasm
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/SecF
> > spWrapperPlatformSecLibSample/X64/Stack.nasm
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForF
> > spSmmDxe/PrepareForFspSmmDxe.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForF
> > spSmmDxe/PrepareForFspSmmDxe.inf
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForF
> > spSmmDxeFsp/PrepareForFspSmmDxeFsp.c
> > create mode 100644
> >
> Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareForF
> > spSmmDxeFsp/PrepareForFspSmmDxeFsp.inf
> >
> > diff --git
> >
> a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Relea
> > se_Notes.txt
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Rele
> > ase_Notes.txt
> > new file mode 100644
> > index 0000000000..92e8f7a43b
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FSP_Rele
> > ase_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/Fsp2Wra
> > pperPkg.dec
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2Wra
> > pperPkg.dec
> > new file mode 100644
> > index 0000000000..25327755e6
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Fsp2Wra
> > pperPkg.dec
> > @@ -0,0 +1,167 @@
> > +## @file
> > +# EDK II Fsp2WrapperPkg.dec file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +##
> > +
>
> Please put AMD copy right under Intel's.
>
> > +## @file
> > +# Provides drivers and definitions to support fsp in EDKII bios.
> > +#
> > +# 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/FspWrapperMultiPhasePr
> > ocessLib.h
> > +
> > + ## @libraryclass Provide MultiPhase platform actions related functions.
> > +
> >
> FspWrapperPlatformMultiPhaseLib|Include/Library/FspWrapperPlatformMul
> > tiPhaseLib.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|UI
> > NT32|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|UINT
> > 32|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|0x
> > 40000009
> > +
> > + ## 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|UIN
> > T8|0x4000000A
> > +
> > + #
> > + ## These are the base address of FSP-M/S
> > + #
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInFlash|0x00000000|U
> > INT32|0x00001000
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInFlash|0x00000000|UI
> > NT32|0x00001001
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspoPeiBaseAddressInFlash|0x00000000|
> > UINT32|0x00001002
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspoDxeBaseAddressInFlash|0x00000000
> > |UINT32|0x00001003
> > +
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddressInMemory|0x0000000
> > 0|UINT32|0x00002000
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddressInMemory|0x00000000
> > |UINT32|0x00002001
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspoPeiBaseAddressInMemory|0x000000
> > 00|UINT32|0x00002002
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspoDxeBaseAddressInMemory|0x00000
> > 000|UINT32|0x00002003
> > +
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspmRegionSize|0x00000000|UINT32|0x
> > 00003000
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspsRegionSize|0x00000000|UINT32|0x
> > 00003001
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspoPeiRegionSize|0x00000000|UINT32|
> > 0x00003002
> > +
> >
> gFsp2WrapperTokenSpaceGuid.PcdFspoDxeRegionSize|0x00000000|UINT32
> > |0x00003003
> > +
> > +
> >
> gFsp2WrapperTokenSpaceGuid.FspoPeiWorkaroundShadowCopyAddress|0x
> > 09E00000|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|0x0000000
> > 0|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/FspWrap
> > perNotifyDxe/FspWrapperNotifyDxe.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> > perNotifyDxe/FspWrapperNotifyDxe.c
> > new file mode 100644
> > index 0000000000..0c997b40d0
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> > perNotifyDxe/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/FspWrap
> > perNotifyDxe/FspWrapperNotifyDxe.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> > perNotifyDxe/FspWrapperNotifyDxe.inf
> > new file mode 100644
> > index 0000000000..9ec6de6a13
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> > perNotifyDxe/FspWrapperNotifyDxe.inf
> > @@ -0,0 +1,82 @@
> > +## @file
> > +# FSP-S wrapper Notify DXE Module INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
>
>
> Please put AMD copy right under Intel's.
>
>
>
> > +
> > +## @file
> > +# FSP DXE Module
> > +#
> > +# This driver will register two callbacks to call fsp's notifies.
> > +#
> > +# 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/FspWrap
> > perNotifyDxe/LoadBelow4G.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> > perNotifyDxe/LoadBelow4G.c
> > new file mode 100644
> > index 0000000000..9a49d3b492
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspWrap
> > perNotifyDxe/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))(NewImage
> > Handle, 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/FspmWra
> > pperPeim/FspmWrapperPeim.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWra
> > pperPeim/FspmWrapperPeim.c
> > new file mode 100644
> > index 0000000000..fc5a339e8b
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWra
> > pperPeim/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/FspmWra
> > pperPeim/FspmWrapperPeim.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWra
> > pperPeim/FspmWrapperPeim.inf
> > new file mode 100644
> > index 0000000000..ced1873a44
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspmWra
> > pperPeim/FspmWrapperPeim.inf
> > @@ -0,0 +1,99 @@
> > +## @file
> > +# FSP-M wrapper PEI Module INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
>
> Please put AMD copy right under Intel's.
>
>
> > +
> > +## @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) 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/FspsMulti
> > PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> > PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.c
> > new file mode 100644
> > index 0000000000..bb5e12cba9
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> > PhaseSiInitDxe/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/FspsMulti
> > PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> > PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
> > new file mode 100644
> > index 0000000000..7eefe691cf
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> > PhaseSiInitDxe/FspsMultiPhaseSiInitDxe.inf
> > @@ -0,0 +1,81 @@
> > +## @file
> > +# FSP DXE Module INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
>
> Please put AMD copy right under Intel's.
>
> > +## @file
> > +# FSP DXE Module
> > +#
> > +# This driver will register two callbacks to call fsp's notifies.
> > +#
> > +# 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.PcdAmdFspSetupTableInitNeedsRe
> > set
> > +
> > +[Depex]
> > + TRUE
> > diff --git
> >
> a/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> > PhaseSiInitDxe/LoadBelow4G.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> > PhaseSiInitDxe/LoadBelow4G.c
> > new file mode 100644
> > index 0000000000..ae05556cc9
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsMulti
> > PhaseSiInitDxe/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))(NewImage
> > Handle, 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/FspsWrap
> > perPeim/FspsWrapperPeim.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrap
> > perPeim/FspsWrapperPeim.c
> > new file mode 100644
> > index 0000000000..e6a589bcb5
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrap
> > perPeim/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/FspsWrap
> > perPeim/FspsWrapperPeim.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrap
> > perPeim/FspsWrapperPeim.inf
> > new file mode 100644
> > index 0000000000..e43a8c941f
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/FspsWrap
> > perPeim/FspsWrapperPeim.inf
> > @@ -0,0 +1,98 @@
> > +## @file
> > +# FSP-S wrapper PEI Module INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +## @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) 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/F
> > spExportedInterfaceHob.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spExportedInterfaceHob.h
> > new file mode 100644
> > index 0000000000..66778b0143
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spExportedInterfaceHob.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/F
> > spMemoryRegionHob.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spMemoryRegionHob.h
> > new file mode 100644
> > index 0000000000..3319cad3bc
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spMemoryRegionHob.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/F
> > spSmmDataExchangeBuffer.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spSmmDataExchangeBuffer.h
> > new file mode 100644
> > index 0000000000..1eaa187bb8
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spSmmDataExchangeBuffer.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/F
> > spUpd.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spUpd.h
> > new file mode 100644
> > index 0000000000..a4827a0068
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spUpd.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/F
> > spmUpd.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spmUpd.h
> > new file mode 100644
> > index 0000000000..ed9a6c79a3
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spmUpd.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/F
> > spsUpd.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spsUpd.h
> > new file mode 100644
> > index 0000000000..c1fb89c63d
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > spsUpd.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/F
> > sptUpd.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > sptUpd.h
> > new file mode 100644
> > index 0000000000..604efefa7d
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/F
> > sptUpd.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/Li
> > brary/FspMeasurementLib.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/FspMeasurementLib.h
> > new file mode 100644
> > index 0000000000..7172544b8a
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/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/Li
> > brary/FspWrapperApiLib.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/FspWrapperApiLib.h
> > new file mode 100644
> > index 0000000000..073c6e1d0e
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/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/Li
> > brary/FspWrapperApiTestLib.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/FspWrapperApiTestLib.h
> > new file mode 100644
> > index 0000000000..c4e785e41e
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/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/Li
> > brary/FspWrapperHobProcessLib.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/FspWrapperHobProcessLib.h
> > new file mode 100644
> > index 0000000000..8c0c244e43
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/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/Li
> > brary/FspWrapperMultiPhaseProcessLib.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/FspWrapperMultiPhaseProcessLib.h
> > new file mode 100644
> > index 0000000000..89cff5ea4a
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/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/Li
> > brary/FspWrapperPlatformLib.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/FspWrapperPlatformLib.h
> > new file mode 100644
> > index 0000000000..529bc31145
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/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/Li
> > brary/FspWrapperPlatformMultiPhaseLib.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/FspWrapperPlatformMultiPhaseLib.h
> > new file mode 100644
> > index 0000000000..8e16ddb719
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/Li
> > brary/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..9be1b17b29
> > --- /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/P
> > pi/FspSiliconInitDone.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/P
> > pi/FspSiliconInitDone.h
> > new file mode 100644
> > index 0000000000..23d46ea1f1
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/P
> > pi/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/P
> > pi/TopOfTemporaryRam.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/P
> > pi/TopOfTemporaryRam.h
> > new file mode 100644
> > index 0000000000..7bb32290cb
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Include/P
> > pi/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/B
> > aseFspMeasurementLib/BaseFspMeasurementLib.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspMeasurementLib/BaseFspMeasurementLib.inf
> > new file mode 100644
> > index 0000000000..48eb4991dd
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspMeasurementLib/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/B
> > aseFspMeasurementLib/FspMeasurementLib.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspMeasurementLib/FspMeasurementLib.c
> > new file mode 100644
> > index 0000000000..9a9368bb75
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspMeasurementLib/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/B
> > aseFspWrapperApiLib/BaseFspWrapperApiLib.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/BaseFspWrapperApiLib.inf
> > new file mode 100644
> > index 0000000000..e41d17d67c
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/BaseFspWrapperApiLib.inf
> > @@ -0,0 +1,73 @@
> > +## @file
> > +# FSP API related function INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
>
> Please put AMD copy right under Intel's.
>
>
>
> > +
> > +## @file
> > +# Provide FSP API related function.
> > +#
> > +# 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/B
> > aseFspWrapperApiLib/FspWrapperApiLib.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/FspWrapperApiLib.c
> > new file mode 100644
> > index 0000000000..80d64f9bd2
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/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/B
> > aseFspWrapperApiLib/IA32/DispatchExecute.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/IA32/DispatchExecute.c
> > new file mode 100644
> > index 0000000000..434eb549a4
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/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/B
> > aseFspWrapperApiLib/X64/DispatchExecute.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/X64/DispatchExecute.c
> > new file mode 100644
> > index 0000000000..3c34806286
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/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/B
> > aseFspWrapperApiLib/X64/Thunk64To32.nasm
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/X64/Thunk64To32.nasm
> > new file mode 100644
> > index 0000000000..f1a14b2446
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiLib/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/B
> > aseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
> > new file mode 100644
> > index 0000000000..4d40f86b3a
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
> > @@ -0,0 +1,56 @@
> > +## @file
> > +# FSP wrapper API test related function INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
>
> > +### @file
> > +# Provide FSP wrapper API test related function.
> > +#
> > +# 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/B
> > aseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiTestLibNull/FspWrapperApiTestNull.c
> > new file mode 100644
> > index 0000000000..19bd3afc29
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperApiTestLibNull/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/B
> > aseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
> > new file mode 100644
> > index 0000000000..1f66593a52
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
> > @@ -0,0 +1,79 @@
> > +## @file
> > +# FSP wrapper platform related function INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +## @file
> > +# Sample to provide FSP wrapper platform related function.
> > +#
> > +# 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/B
> > aseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperPlatformLibSample/FspWrapperPlatformLibSample.c
> > new file mode 100644
> > index 0000000000..1afcf68f85
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> > aseFspWrapperPlatformLibSample/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/B
> >
> aseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPha
> > seLibNull.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> >
> aseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPha
> > seLibNull.inf
> > new file mode 100644
> > index 0000000000..f9f1a12c2f
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> >
> aseFspWrapperPlatformMultiPhaseLibNull/BaseFspWrapperPlatformMultiPha
> > seLibNull.inf
> > @@ -0,0 +1,45 @@
> > +## @file
> > +# FSP Wrapper to handle platform specific actions for
> > +# FSP MultiPhase (SeparatePhase) Initialization.
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +## @file
> > +# FSP Wrapper to handle platform specific actions for
> > +# FSP MultiPhase (SeparatePhase) Initialization.
> > +#
> > +# 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/B
> >
> aseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLi
> > bNull.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> >
> aseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLi
> > bNull.c
> > new file mode 100644
> > index 0000000000..3a0d0e6088
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/B
> >
> aseFspWrapperPlatformMultiPhaseLibNull/FspWrapperPlatformMultiPhaseLi
> > bNull.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/D
> >
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/D
> >
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.c
> > new file mode 100644
> > index 0000000000..cfda44bc71
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/D
> >
> xeFspWrapperMultiPhaseProcessLib/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,PcdS3BootScriptTablePrivateSm
> > mDataPtr:%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/D
> >
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.in
> > f
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/D
> >
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.in
> > f
> > new file mode 100644
> > index 0000000000..21912fba99
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/D
> >
> xeFspWrapperMultiPhaseProcessLib/DxeFspWrapperMultiPhaseProcessLib.in
> > f
> > @@ -0,0 +1,87 @@
> > +## @file
> > +# FSP wrapper DXE FSP MultiPhase (SeparatePhase) INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +## @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.PcdAmdSmmCommunicationAddr
> > ess ## 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/Fs
> > pWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fs
> > pWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
> > new file mode 100644
> > index 0000000000..6f681780e3
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fs
> > pWrapperMultiPhaseProcessLib/FspWrapperMultiPhaseProcessLib.inf
> > @@ -0,0 +1,56 @@
> > +## @file
> > +# FSP wrapper PEI FSP MultiPhase (SeparatePhase) INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +## @file
> > +# FSP wrapper to handle FSP MultiPhase (SeparatePhase) Initialization.
> > +#
> > +# 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/Fs
> > pWrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fs
> > pWrapperMultiPhaseProcessLib/PeiFspWrapperMultiPhaseProcessLib.c
> > new file mode 100644
> > index 0000000000..e072efbb04
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/Fs
> > pWrapperMultiPhaseProcessLib/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/Pe
> > iFspWrapperApiTestLib/FspWrapperApiTest.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperApiTestLib/FspWrapperApiTest.c
> > new file mode 100644
> > index 0000000000..caffada924
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperApiTestLib/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/Pe
> > iFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
> > new file mode 100644
> > index 0000000000..5b378c6c55
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
> > @@ -0,0 +1,59 @@
> > +## @file
> > +# FSP wrapper FSP-M wrapper API test INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +### @file
> > +# Provide FSP-M wrapper API test related function.
> > +#
> > +# 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/Pe
> > iFspWrapperHobProcessLibSample/CommonHeader.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperHobProcessLibSample/CommonHeader.h
> > new file mode 100644
> > index 0000000000..d512feaa5b
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperHobProcessLibSample/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/Pe
> > iFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperHobProcessLibSample/FspWrapperHobProcessLibSample.c
> > new file mode 100644
> > index 0000000000..3100f4635e
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperHobProcessLibSample/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/Pe
> > iFspWrapperHobProcessLibSample/MemoryInstall.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperHobProcessLibSample/MemoryInstall.h
> > new file mode 100644
> > index 0000000000..c9a58aea56
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> > eiFspWrapperHobProcessLibSample/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/Pe
> > iFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> >
> eiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
> > new file mode 100644
> > index 0000000000..6fdfb8e34c
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/P
> >
> eiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
> > @@ -0,0 +1,128 @@
> > +## @file
> > +# FSP wrapper hob process INF file
> > +#
> > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +## @file
> > +# Sample to provide FSP wrapper hob process related function.
> > +#
> > +# 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.PcdAmdFabricResourceDefaultSize
> > Ptr
> > +[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/Se
> > cFspWrapperPlatformSecLibSample/Fsp.h
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/Fsp.h
> > new file mode 100644
> > index 0000000000..0bb612ea87
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/FspWrapperPlatformSecLibSample.c
> > new file mode 100644
> > index 0000000000..54f363e59d
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/Ia32/PeiCoreEntry.nasm
> > new file mode 100644
> > index 0000000000..cf443aa267
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/Ia32/SecEntry.nasm
> > new file mode 100644
> > index 0000000000..b506212bfa
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/Ia32/Stack.nasm
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/Ia32/Stack.nasm
> > new file mode 100644
> > index 0000000000..48101131fa
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/PlatformInit.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/PlatformInit.c
> > new file mode 100644
> > index 0000000000..237aeead51
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> >
> cFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> >
> ecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.in
> > f
> > new file mode 100644
> > index 0000000000..ac417c8e59
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> >
> ecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.in
> > f
> > @@ -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/Se
> > cFspWrapperPlatformSecLibSample/SecGetPerformance.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/SecGetPerformance.c
> > new file mode 100644
> > index 0000000000..449a2d6e99
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/SecPlatformInformation.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/SecPlatformInformation.c
> > new file mode 100644
> > index 0000000000..b96f38432e
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/SecRamInitData.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/SecRamInitData.c
> > new file mode 100644
> > index 0000000000..5e7f051bb6
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/SecTempRamDone.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/SecTempRamDone.c
> > new file mode 100644
> > index 0000000000..fab488e668
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/X64/PeiCoreEntry.nasm
> > new file mode 100644
> > index 0000000000..548474ccbb
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/X64/SecEntry.nasm
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/X64/SecEntry.nasm
> > new file mode 100644
> > index 0000000000..4025b4157c
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/Se
> > cFspWrapperPlatformSecLibSample/X64/Stack.nasm
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/X64/Stack.nasm
> > new file mode 100644
> > index 0000000000..6feb38ce02
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/Library/S
> > ecFspWrapperPlatformSecLibSample/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/PrepareF
> > orFspSmmDxe/PrepareForFspSmmDxe.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> > orFspSmmDxe/PrepareForFspSmmDxe.c
> > new file mode 100644
> > index 0000000000..87abe27c09
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> > orFspSmmDxe/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/PrepareF
> > orFspSmmDxe/PrepareForFspSmmDxe.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> > orFspSmmDxe/PrepareForFspSmmDxe.inf
> > new file mode 100644
> > index 0000000000..03d6c9d668
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> > orFspSmmDxe/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/PrepareF
> > orFspSmmDxeFsp/PrepareForFspSmmDxeFsp.c
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> > orFspSmmDxeFsp/PrepareForFspSmmDxeFsp.c
> > new file mode 100644
> > index 0000000000..05e5a0bd08
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> > orFspSmmDxeFsp/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/PrepareF
> > orFspSmmDxeFsp/PrepareForFspSmmDxeFsp.inf
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> > orFspSmmDxeFsp/PrepareForFspSmmDxeFsp.inf
> > new file mode 100644
> > index 0000000000..19dd25b27f
> > --- /dev/null
> > +++
> >
> b/Platform/AMD/VanGoghBoard/Override/edk2/Fsp2WrapperPkg/PrepareF
> > orFspSmmDxeFsp/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 (#114569): https://edk2.groups.io/g/devel/message/114569
Mute This Topic: https://groups.io/mt/103971425/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 V2 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module.
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (26 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 27/32] AMD/VanGoghBoard: Check in Fsp2WrapperPkg Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114521): https://edk2.groups.io/g/devel/message/114521
Mute This Topic: https://groups.io/mt/103971423/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 V2 29/32] AMD/VanGoghBoard: Check in SmramSaveState module
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (27 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 28/32] AMD/VanGoghBoard: Check in SmmCpuFeaturesLibCommon module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114520): https://edk2.groups.io/g/devel/message/114520
Mute This Topic: https://groups.io/mt/103971420/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 V2 30/32] AMD/VanGoghBoard: Check in EDK2 override files
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (28 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 29/32] AMD/VanGoghBoard: Check in SmramSaveState module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 9:37 ` Chang, Abner via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module Zhai, MingXin (Duke) via groups.io
` (2 subsequent siblings)
32 siblings, 1 reply; 39+ messages in thread
From: Zhai, MingXin (Duke) via groups.io @ 2024-01-26 6:00 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:
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 | 366 ++++
.../edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c | 1876 +++++++++++++++++
.../MdeModulePkg/Universal/PCD/Pei/Pcd.inf | 368 ++++
.../Register/Intel/SmramSaveStateMap.h | 324 +++
5 files changed, 4454 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..0799e4cd96
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
@@ -0,0 +1,366 @@
+## @file
+# PCD DXE Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @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) 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..204f08b958
--- /dev/null
+++ b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.inf
@@ -0,0 +1,368 @@
+## @file
+# PCD PEI Module INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+## @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) 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..05487d75e9
--- /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 (#114522): https://edk2.groups.io/g/devel/message/114522
Mute This Topic: https://groups.io/mt/103971424/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
* Re: [edk2-devel] [PATCH V2 30/32] AMD/VanGoghBoard: Check in EDK2 override files
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 30/32] AMD/VanGoghBoard: Check in EDK2 override files Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 9:37 ` Chang, Abner via groups.io
0 siblings, 0 replies; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-26 9:37 UTC (permalink / raw)
To: Zhai, MingXin (Duke), devel@edk2.groups.io; +Cc: Xing, Eric, Fu, Igniculus
[AMD Official Use Only - General]
> -----Original Message-----
> From: Zhai, MingXin (Duke) <duke.zhai@amd.com>
> Sent: Friday, January 26, 2024 2:01 PM
> To: devel@edk2.groups.io
> Cc: Xing, Eric <Eric.Xing@amd.com>; Zhai, MingXin (Duke)
> <duke.zhai@amd.com>; Fu, Igniculus <Igniculus.Fu@amd.com>; Chang,
> Abner <Abner.Chang@amd.com>
> Subject: [PATCH V2 30/32] AMD/VanGoghBoard: Check in EDK2 override files
>
> 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:
> 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 | 366 ++++
> .../edk2/MdeModulePkg/Universal/PCD/Pei/Pcd.c | 1876
> +++++++++++++++++
> .../MdeModulePkg/Universal/PCD/Pei/Pcd.inf | 368 ++++
> .../Register/Intel/SmramSaveStateMap.h | 324 +++
> 5 files changed, 4454 insertions(+)
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PC
> D/Dxe/Pcd.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PC
> D/Dxe/Pcd.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PC
> D/Pei/Pcd.c
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/PC
> D/Pei/Pcd.inf
> create mode 100644
> Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/Inte
> l/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..0799e4cd96
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> PCD/Dxe/Pcd.inf
> @@ -0,0 +1,366 @@
> +## @file
> +# PCD DXE Module INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
Please put AMD copy right under Intel's.
> +
> +## @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) 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..204f08b958
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdeModulePkg/Universal/
> PCD/Pei/Pcd.inf
> @@ -0,0 +1,368 @@
> +## @file
> +# PCD PEI Module INF file
> +#
> +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
Please put AMD copy right under Intel's.
Thanks
Abner
> +
> +## @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) 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.PcdMaxPeiPcdCallBackNumberPerPcdEntr
> y ## 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/I
> ntel/SmramSaveStateMap.h
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/I
> ntel/SmramSaveStateMap.h
> new file mode 100644
> index 0000000000..05487d75e9
> --- /dev/null
> +++
> b/Platform/AMD/VanGoghBoard/Override/edk2/MdePkg/Include/Register/I
> ntel/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 (#114570): https://edk2.groups.io/g/devel/message/114570
Mute This Topic: https://groups.io/mt/103971424/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 V2 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (29 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 30/32] AMD/VanGoghBoard: Check in EDK2 override files Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script Zhai, MingXin (Duke) via groups.io
2024-01-26 9:48 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114524): https://edk2.groups.io/g/devel/message/114524
Mute This Topic: https://groups.io/mt/103971434/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 V2 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (30 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 31/32] AMD/VanGoghBoard: Check in AMD SmmControlPei module Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 6:00 ` Zhai, MingXin (Duke) via groups.io
2024-01-26 9:48 ` [edk2-devel] [PATCH V2 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 6:00 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 (#114525): https://edk2.groups.io/g/devel/message/114525
Mute This Topic: https://groups.io/mt/103971436/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 V2 00/32] Introduce AMD Vangogh platform reference code
2024-01-26 6:00 [edk2-devel] [PATCH V2 00/32] Introduce AMD Vangogh platform reference code Zhai, MingXin (Duke) via groups.io
` (31 preceding siblings ...)
2024-01-26 6:00 ` [edk2-devel] [PATCH V2 32/32] AMD/VanGoghBoard: Check in Chachani board project files and build script Zhai, MingXin (Duke) via groups.io
@ 2024-01-26 9:48 ` Chang, Abner via groups.io
32 siblings, 0 replies; 39+ messages in thread
From: Chang, Abner via groups.io @ 2024-01-26 9:48 UTC (permalink / raw)
To: Zhai, MingXin, devel
[-- Attachment #1: Type: text/plain, Size: 726 bytes --]
Hi Duke,
Besides the AMD copyright is put in an improper place. I also found that there are several #include guards that don't follow edk2 C coding standard. There are several trailing underscores (like four underscores) attached to the macro. Please just put one trailing underscore as "INCLUDE_GUARD_".
Please send out V3 with the fixes.
Thanks
Abenr
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114571): https://edk2.groups.io/g/devel/message/114571
Mute This Topic: https://groups.io/mt/103971387/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: 1158 bytes --]
^ permalink raw reply [flat|nested] 39+ messages in thread