summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:49:04 +0000
commit16f504a9dca3fe3b70568f67b7d41241ae485288 (patch)
treec60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg
parentInitial commit. (diff)
downloadvirtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.tar.xz
virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.zip
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg')
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.c149
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.h17
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf43
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf52
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf66
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf52
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf54
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/Fsp22ApiEntryS.nasm99
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm73
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm247
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryS.nasm67
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm539
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm35
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/MicrocodeLoadNasm.inc10
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/ReadEsp.nasm22
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/SaveRestoreSseNasm.inc181
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/Stack.nasm72
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFsp.c218
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFsp.h93
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c91
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.c301
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.h138
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.rawbin0 -> 68 bytes
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Build.py47
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Ia16/ResetVec.asm1697
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/ResetVectorCode.asm11
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py104
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas.h18
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas/FspApi.h485
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspGlobalData.h78
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspMeasurePointId.h56
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspStatusCode.h40
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h204
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Guid/GuidHobFspEas.h17
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/CacheAsRamLib.h24
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/CacheLib.h56
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/DebugDeviceLib.h23
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspCommonLib.h308
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspPlatformLib.h125
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspSecPlatformLib.h96
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspSwitchStackLib.h55
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Ppi/FspmArchConfigPpi.h47
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Ppi/TempRamExitPpi.h52
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dec109
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dsc80
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf26
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c35
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf29
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c697
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/CacheLibInternal.h53
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf29
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c25
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf30
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c545
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf45
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/DebugLib.c415
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.nasm25
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf40
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformMemory.c116
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformNotify.c409
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf33
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c36
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/Ia32/Stack.nasm68
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/Flat32.nasm121
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/SecCarInit.nasm40
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/PlatformSecLibNull.c44
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf51
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Readme.md7
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py884
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/GenCfgOpt.py1791
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/PatchFv.py954
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/SplitFspBin.py892
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h75
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h69
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h87
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf88
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml267
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc471
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py96
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md39
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/GenCfgOptUserManual.md353
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/PatchFvUserManual.md123
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/SplitFspBinUserManual.md72
84 files changed, 13947 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.c
new file mode 100644
index 00000000..cf27e462
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.c
@@ -0,0 +1,149 @@
+/** @file
+ Source file for FSP notify phase PEI module
+
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "FspNotifyPhasePeim.h"
+
+/**
+
+ This function waits for FSP notify.
+
+ @param This Entry point for DXE IPL PPI.
+ @param PeiServices General purpose services available to every PEIM.
+ @param HobList Address to the Pei HOB list.
+
+ @return EFI_SUCCESS This function never returns.
+
+**/
+EFI_STATUS
+EFIAPI
+WaitForNotify (
+ IN CONST EFI_DXE_IPL_PPI *This,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_HOB_POINTERS HobList
+ );
+
+CONST EFI_DXE_IPL_PPI mDxeIplPpi = {
+ WaitForNotify
+};
+
+CONST EFI_PEI_PPI_DESCRIPTOR mInstallDxeIplPpi = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gEfiDxeIplPpiGuid,
+ (VOID *) &mDxeIplPpi
+};
+
+CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ NULL
+};
+
+CONST EFI_PEI_PPI_DESCRIPTOR gFspReadyForNotifyPhasePpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gFspReadyForNotifyPhasePpiGuid,
+ NULL
+};
+
+/**
+
+ This function waits for FSP notify.
+
+ @param This Entry point for DXE IPL PPI.
+ @param PeiServices General purpose services available to every PEIM.
+ @param HobList Address to the Pei HOB list.
+
+ @return EFI_SUCCESS This function never returns.
+
+**/
+EFI_STATUS
+EFIAPI
+WaitForNotify (
+ IN CONST EFI_DXE_IPL_PPI *This,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_HOB_POINTERS HobList
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP HOB is located at 0x%08X\n", HobList));
+
+ //
+ // End of PEI phase signal
+ //
+ Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Give control back to BootLoader after FspSiliconInit
+ //
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP is waiting for NOTIFY\n"));
+ FspSiliconInitDone2 (EFI_SUCCESS);
+
+ //
+ // BootLoader called FSP again through NotifyPhase
+ //
+ FspWaitForNotify ();
+
+ if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {
+ //
+ // Should not come here
+ //
+ while (TRUE) {
+ DEBUG ((DEBUG_ERROR, "No FSP API should be called after FSP is DONE!\n"));
+ SetFspApiReturnStatus (EFI_UNSUPPORTED);
+ Pei2LoaderSwitchStack ();
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ FSP notify phase PEI module entry point
+
+ @param[in] FileHandle Not used.
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS The function completes successfully
+ @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database
+**/
+EFI_STATUS
+FspNotifyPhasePeimEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ VOID *OldDxeIplPpi;
+ EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "The entry of FspNotificationPeim\n"));
+
+ if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {
+ //
+ // Locate old DXE IPL PPI
+ //
+ Status = PeiServicesLocatePpi (
+ &gEfiDxeIplPpiGuid,
+ 0,
+ &OldDescriptor,
+ &OldDxeIplPpi
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Re-install the DXE IPL PPI to wait for notify
+ //
+ Status = PeiServicesReInstallPpi (OldDescriptor, &mInstallDxeIplPpi);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = PeiServicesInstallPpi (&gFspReadyForNotifyPhasePpi);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.h
new file mode 100644
index 00000000..a33c9b60
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.h
@@ -0,0 +1,17 @@
+/** @file
+ Header file for FSP notify phase PEI module
+
+ Copyright (c) 2016 Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _FSP_NOTIFY_PHASE_PEIM_H_
+#define _FSP_NOTIFY_PHASE_PEIM_H_
+
+#include <Library/PeiServicesLib.h>
+#include <Ppi/DxeIpl.h>
+#include <Library/DebugLib.h>
+#include <Library/FspPlatformLib.h>
+#include <Library/FspCommonLib.h>
+#include <Library/FspSwitchStackLib.h>
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf
new file mode 100644
index 00000000..5db41318
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf
@@ -0,0 +1,43 @@
+## @file
+# Component information file for the FSP notify phase PEI module.
+#
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FspNotifyPhasePeim
+ FILE_GUID = 29CBB005-C972-49F3-960F-292E2202CECD
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = FspNotifyPhasePeimEntryPoint
+
+[Sources]
+ FspNotifyPhasePeim.h
+ FspNotifyPhasePeim.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ DebugLib
+ FspPlatformLib
+ FspCommonLib
+ FspSwitchStackLib
+
+[Ppis]
+ gEfiDxeIplPpiGuid ## PRODUCES
+ gEfiEndOfPeiSignalPpiGuid ## PRODUCES
+ gFspReadyForNotifyPhasePpiGuid ## PRODUCES
+
+[Protocols]
+ gEfiPciEnumerationCompleteProtocolGuid ## PRODUCES
+
+[Guids]
+ gEfiEventReadyToBootGuid ## PRODUCES ## Event
+
+[Depex]
+ gEfiDxeIplPpiGuid
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
new file mode 100644
index 00000000..c1630481
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
@@ -0,0 +1,52 @@
+## @file
+# Sec Core for FSP to support MultiPhase (SeparatePhase) SiInitialization.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Fsp22SecCoreS
+ FILE_GUID = DF0FCD70-264A-40BF-BBD4-06C76DB19CB1
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ SecFspApiChk.c
+ SecFsp.h
+
+[Sources.IA32]
+ Ia32/Stack.nasm
+ Ia32/Fsp22ApiEntryS.nasm
+ Ia32/FspApiEntryCommon.nasm
+ Ia32/FspHelper.nasm
+
+[Binaries.Ia32]
+ RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ PciCf8Lib
+ SerialPortLib
+ FspSwitchStackLib
+ FspCommonLib
+ FspSecPlatformLib
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid ## PRODUCES
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
new file mode 100644
index 00000000..9c4b058e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
@@ -0,0 +1,66 @@
+## @file
+# Sec Core for FSP
+#
+# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FspSecCoreM
+ FILE_GUID = C2F9AE46-3437-4FEF-9CB1-9A568B282FEE
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ SecMain.c
+ SecMain.h
+ SecFsp.c
+ SecFsp.h
+ SecFspApiChk.c
+
+[Sources.IA32]
+ Ia32/Stack.nasm
+ Ia32/FspApiEntryM.nasm
+ Ia32/FspApiEntryCommon.nasm
+ Ia32/FspHelper.nasm
+ Ia32/ReadEsp.nasm
+
+[Binaries.Ia32]
+ RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ PciCf8Lib
+ SerialPortLib
+ FspSwitchStackLib
+ FspCommonLib
+ FspSecPlatformLib
+ UefiCpuLib
+
+[Pcd]
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspHeapSizePercentage ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxInterruptSupported ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspPrivateTemporaryRamSize ## CONSUMES
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid ## PRODUCES
+ gFspInApiModePpiGuid ## PRODUCES
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf
new file mode 100644
index 00000000..e57a9c69
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf
@@ -0,0 +1,52 @@
+## @file
+# Sec Core for FSP
+#
+# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FspSecCoreS
+ FILE_GUID = 53AB1ACD-EDB1-4E3A-A2C7-978D721D179D
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ SecFspApiChk.c
+ SecFsp.h
+
+[Sources.IA32]
+ Ia32/Stack.nasm
+ Ia32/FspApiEntryS.nasm
+ Ia32/FspApiEntryCommon.nasm
+ Ia32/FspHelper.nasm
+
+[Binaries.Ia32]
+ RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ PciCf8Lib
+ SerialPortLib
+ FspSwitchStackLib
+ FspCommonLib
+ FspSecPlatformLib
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid ## PRODUCES
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
new file mode 100644
index 00000000..ab3e16f9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
@@ -0,0 +1,54 @@
+## @file
+# Sec Core for FSP
+#
+# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FspSecCoreT
+ FILE_GUID = 5B94E419-C795-414D-A0D4-B80A877BE5FE
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+
+
+[Sources.IA32]
+ Ia32/Stack.nasm
+ Ia32/FspApiEntryT.nasm
+ Ia32/FspHelper.nasm
+
+[Binaries.Ia32]
+ RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ PciCf8Lib
+ SerialPortLib
+ FspSwitchStackLib
+ FspCommonLib
+ FspSecPlatformLib
+
+[Pcd]
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedBufferSize ## CONSUMES
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid ## PRODUCES
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/Fsp22ApiEntryS.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/Fsp22ApiEntryS.nasm
new file mode 100644
index 00000000..ab634ff2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/Fsp22ApiEntryS.nasm
@@ -0,0 +1,99 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+;
+; Following functions will be provided in C
+;
+extern ASM_PFX(FspApiCommon)
+extern ASM_PFX(FspMultiPhaseSiInitApiHandler)
+
+;----------------------------------------------------------------------------
+; NotifyPhase API
+;
+; This FSP API will notify the FSP about the different phases in the boot
+; process
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(NotifyPhaseApi)
+ASM_PFX(NotifyPhaseApi):
+ mov eax, 2 ; FSP_API_INDEX.NotifyPhaseApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspSiliconInit API
+;
+; This FSP API initializes the CPU and the chipset including the IO
+; controllers in the chipset to enable normal operation of these devices.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspSiliconInitApi)
+ASM_PFX(FspSiliconInitApi):
+ mov eax, 5 ; FSP_API_INDEX.FspSiliconInitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspMultiPhaseSiInitApi API
+;
+; This FSP API provides multi-phase silicon initialization, which brings greater
+; modularity beyond the existing FspSiliconInit() API.
+; Increased modularity is achieved by adding an extra API to FSP-S.
+; This allows the bootloader to add board specific initialization steps throughout
+; the SiliconInit flow as needed.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspMultiPhaseSiInitApi)
+ASM_PFX(FspMultiPhaseSiInitApi):
+ mov eax, 6 ; FSP_API_INDEX.FspMultiPhaseSiInitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspApiCommonContinue API
+;
+; This is the FSP API common entry point to resume the FSP execution
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspApiCommonContinue)
+ASM_PFX(FspApiCommonContinue):
+ ;
+ ; Handle FspMultiPhaseSiInitApiIndex API
+ ;
+ cmp eax, 6
+ jnz NotMultiPhaseSiInitApi
+
+ pushad
+ push DWORD [esp + (4 * 8 + 4)] ; push ApiParam
+ push eax ; push ApiIdx
+ call ASM_PFX(FspMultiPhaseSiInitApiHandler)
+ add esp, 8
+ mov dword [esp + (4 * 7)], eax
+ popad
+ ret
+
+NotMultiPhaseSiInitApi:
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; TempRamInit API
+;
+; Empty function for WHOLEARCHIVE build option
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamInitApi)
+ASM_PFX(TempRamInitApi):
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; Module Entrypoint API
+;----------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ jmp $
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
new file mode 100644
index 00000000..050bf9ed
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm
@@ -0,0 +1,73 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+;
+; Following functions will be provided in C
+;
+extern ASM_PFX(Loader2PeiSwitchStack)
+extern ASM_PFX(FspApiCallingCheck)
+
+;
+; Following functions will be provided in ASM
+;
+extern ASM_PFX(FspApiCommonContinue)
+extern ASM_PFX(AsmGetFspInfoHeader)
+
+;----------------------------------------------------------------------------
+; FspApiCommon API
+;
+; This is the FSP API common entry point to resume the FSP execution
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspApiCommon)
+ASM_PFX(FspApiCommon):
+ ;
+ ; EAX holds the API index
+ ;
+
+ ;
+ ; Stack must be ready
+ ;
+ push eax
+ add esp, 4
+ cmp eax, dword [esp - 4]
+ jz FspApiCommon1
+ mov eax, 080000003h
+ jmp exit
+
+FspApiCommon1:
+ ;
+ ; Verify the calling condition
+ ;
+ pushad
+ push DWORD [esp + (4 * 8 + 4)] ; push ApiParam
+ push eax ; push ApiIdx
+ call ASM_PFX(FspApiCallingCheck)
+ add esp, 8
+ cmp eax, 0
+ jz FspApiCommon2
+ mov dword [esp + (4 * 7)], eax
+ popad
+exit:
+ ret
+
+FspApiCommon2:
+ popad
+ cmp eax, 3 ; FspMemoryInit API
+ jz FspApiCommon3
+
+ cmp eax, 6 ; FspMultiPhaseSiInitApiIndex API
+ jz FspApiCommon3
+
+ call ASM_PFX(AsmGetFspInfoHeader)
+ jmp ASM_PFX(Loader2PeiSwitchStack)
+
+FspApiCommon3:
+ jmp ASM_PFX(FspApiCommonContinue)
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm
new file mode 100644
index 00000000..cc420059
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm
@@ -0,0 +1,247 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+;
+; Following are fixed PCDs
+;
+extern ASM_PFX(PcdGet32(PcdTemporaryRamBase))
+extern ASM_PFX(PcdGet32(PcdTemporaryRamSize))
+extern ASM_PFX(PcdGet32(PcdFspTemporaryRamSize))
+extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))
+
+struc FSPM_UPD_COMMON
+ ; FSP_UPD_HEADER {
+ .FspUpdHeader: resd 8
+ ; }
+ ; FSPM_ARCH_UPD {
+ .Revision: resb 1
+ .Reserved: resb 3
+ .NvsBufferPtr: resd 1
+ .StackBase: resd 1
+ .StackSize: resd 1
+ .BootLoaderTolumSize: resd 1
+ .BootMode: resd 1
+ .Reserved1: resb 8
+ ; }
+ .size:
+endstruc
+
+;
+; Following functions will be provided in C
+;
+extern ASM_PFX(SecStartup)
+extern ASM_PFX(FspApiCommon)
+
+;
+; Following functions will be provided in PlatformSecLib
+;
+extern ASM_PFX(AsmGetFspBaseAddress)
+extern ASM_PFX(AsmGetFspInfoHeader)
+
+API_PARAM1_OFFSET EQU 34h ; ApiParam1 [ sub esp,8 + pushad + pushfd + push eax + call]
+FSP_HEADER_IMGBASE_OFFSET EQU 1Ch
+FSP_HEADER_CFGREG_OFFSET EQU 24h
+
+;----------------------------------------------------------------------------
+; FspMemoryInit API
+;
+; This FSP API is called after TempRamInit and initializes the memory.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspMemoryInitApi)
+ASM_PFX(FspMemoryInitApi):
+ mov eax, 3 ; FSP_API_INDEX.FspMemoryInitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; TempRamExitApi API
+;
+; This API tears down temporary RAM
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamExitApi)
+ASM_PFX(TempRamExitApi):
+ mov eax, 4 ; FSP_API_INDEX.TempRamExitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspApiCommonContinue API
+;
+; This is the FSP API common entry point to resume the FSP execution
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspApiCommonContinue)
+ASM_PFX(FspApiCommonContinue):
+ ;
+ ; EAX holds the API index
+ ;
+
+ ;
+ ; FspMemoryInit API setup the initial stack frame
+ ;
+
+ ;
+ ; Place holder to store the FspInfoHeader pointer
+ ;
+ push eax
+
+ ;
+ ; Update the FspInfoHeader pointer
+ ;
+ push eax
+ call ASM_PFX(AsmGetFspInfoHeader)
+ mov [esp + 4], eax
+ pop eax
+
+ ;
+ ; Create a Task Frame in the stack for the Boot Loader
+ ;
+ pushfd ; 2 pushf for 4 byte alignment
+ cli
+ pushad
+
+ ; Reserve 8 bytes for IDT save/restore
+ sub esp, 8
+ sidt [esp]
+
+
+ ; Get Stackbase and StackSize from FSPM_UPD Param
+ mov edx, [esp + API_PARAM1_OFFSET]
+ cmp edx, 0
+ jnz FspStackSetup
+
+ ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null
+ push eax
+ call ASM_PFX(AsmGetFspInfoHeader)
+ mov edx, [eax + FSP_HEADER_IMGBASE_OFFSET]
+ add edx, [eax + FSP_HEADER_CFGREG_OFFSET]
+ pop eax
+
+FspStackSetup:
+ ;
+ ; StackBase = temp memory base, StackSize = temp memory size
+ ;
+ mov edi, [edx + FSPM_UPD_COMMON.StackBase]
+ mov ecx, [edx + FSPM_UPD_COMMON.StackSize]
+
+ ;
+ ; Keep using bootloader stack if heap size % is 0
+ ;
+ mov bl, BYTE [ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))]
+ cmp bl, 0
+ jz SkipStackSwitch
+
+ ;
+ ; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0
+ ;
+ add edi, ecx
+ ;
+ ; Switch to new FSP stack
+ ;
+ xchg edi, esp ; Exchange edi and esp, edi will be assigned to the current esp pointer and esp will be Stack base + Stack size
+
+SkipStackSwitch:
+ ;
+ ; If heap size % is 0:
+ ; EDI is FSPM_UPD_COMMON.StackBase and will hold ESP later (boot loader stack pointer)
+ ; ECX is FSPM_UPD_COMMON.StackSize
+ ; ESP is boot loader stack pointer (no stack switch)
+ ; BL is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON.StackBase later)
+ ;
+ ; If heap size % is not 0
+ ; EDI is boot loader stack pointer
+ ; ECX is FSPM_UPD_COMMON.StackSize
+ ; ESP is new stack (FSPM_UPD_COMMON.StackBase + FSPM_UPD_COMMON.StackSize)
+ ; BL is NOT 0 to indicate stack has switched
+ ;
+ cmp bl, 0
+ jnz StackHasBeenSwitched
+
+ mov ebx, edi ; Put FSPM_UPD_COMMON.StackBase to ebx as temp memory base
+ mov edi, esp ; Put boot loader stack pointer to edi
+ jmp StackSetupDone
+
+StackHasBeenSwitched:
+ mov ebx, esp ; Put Stack base + Stack size in ebx
+ sub ebx, ecx ; Stack base + Stack size - Stack size as temp memory base
+
+StackSetupDone:
+
+ ;
+ ; Pass the API Idx to SecStartup
+ ;
+ push eax
+
+ ;
+ ; Pass the BootLoader stack to SecStartup
+ ;
+ push edi
+
+ ;
+ ; Pass entry point of the PEI core
+ ;
+ call ASM_PFX(AsmGetFspBaseAddress)
+ mov edi, eax
+ call ASM_PFX(AsmGetPeiCoreOffset)
+ add edi, eax
+ push edi
+
+ ;
+ ; Pass BFV into the PEI Core
+ ; It uses relative address to calculate the actual boot FV base
+ ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and
+ ; PcdFspAreaBaseAddress are the same. For FSP with multiple FVs,
+ ; they are different. The code below can handle both cases.
+ ;
+ call ASM_PFX(AsmGetFspBaseAddress)
+ push eax
+
+ ;
+ ; Pass stack base and size into the PEI Core
+ ;
+ push ebx
+ push ecx
+
+ ;
+ ; Pass Control into the PEI Core
+ ;
+ call ASM_PFX(SecStartup)
+ add esp, 4
+exit:
+ ret
+
+global ASM_PFX(FspPeiCoreEntryOff)
+ASM_PFX(FspPeiCoreEntryOff):
+ ;
+ ; This value will be pached by the build script
+ ;
+ DD 0x12345678
+
+global ASM_PFX(AsmGetPeiCoreOffset)
+ASM_PFX(AsmGetPeiCoreOffset):
+ mov eax, dword [ASM_PFX(FspPeiCoreEntryOff)]
+ ret
+
+;----------------------------------------------------------------------------
+; TempRamInit API
+;
+; Empty function for WHOLEARCHIVE build option
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamInitApi)
+ASM_PFX(TempRamInitApi):
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; Module Entrypoint API
+;----------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ jmp $
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryS.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryS.nasm
new file mode 100644
index 00000000..a7424c5f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryS.nasm
@@ -0,0 +1,67 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+;
+; Following functions will be provided in C
+;
+extern ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; NotifyPhase API
+;
+; This FSP API will notify the FSP about the different phases in the boot
+; process
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(NotifyPhaseApi)
+ASM_PFX(NotifyPhaseApi):
+ mov eax, 2 ; FSP_API_INDEX.NotifyPhaseApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspSiliconInit API
+;
+; This FSP API initializes the CPU and the chipset including the IO
+; controllers in the chipset to enable normal operation of these devices.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspSiliconInitApi)
+ASM_PFX(FspSiliconInitApi):
+ mov eax, 5 ; FSP_API_INDEX.FspSiliconInitApiIndex
+ jmp ASM_PFX(FspApiCommon)
+
+;----------------------------------------------------------------------------
+; FspApiCommonContinue API
+;
+; This is the FSP API common entry point to resume the FSP execution
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(FspApiCommonContinue)
+ASM_PFX(FspApiCommonContinue):
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; TempRamInit API
+;
+; Empty function for WHOLEARCHIVE build option
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamInitApi)
+ASM_PFX(TempRamInitApi):
+ jmp $
+ ret
+
+;----------------------------------------------------------------------------
+; Module Entrypoint API
+;----------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ jmp $
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
new file mode 100644
index 00000000..c831a147
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
@@ -0,0 +1,539 @@
+;; @file
+; Provide FSP API entry points.
+;
+; Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+%include "SaveRestoreSseNasm.inc"
+%include "MicrocodeLoadNasm.inc"
+
+;
+; Following are fixed PCDs
+;
+extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
+extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
+extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
+
+;
+; Following functions will be provided in PlatformSecLib
+;
+extern ASM_PFX(AsmGetFspBaseAddress)
+extern ASM_PFX(AsmGetFspInfoHeader)
+;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation
+extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation
+extern ASM_PFX(SecCarInit)
+
+;
+; Define the data length that we saved on the stack top
+;
+DATA_LEN_OF_PER0 EQU 18h
+DATA_LEN_OF_MCUD EQU 18h
+DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
+
+;
+; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid
+; build error. This needs to be fixed later on.
+;
+struc MicrocodeHdr
+ .MicrocodeHdrVersion: resd 1
+ .MicrocodeHdrRevision: resd 1
+ .MicrocodeHdrDate: resd 1
+ .MicrocodeHdrProcessor: resd 1
+ .MicrocodeHdrChecksum: resd 1
+ .MicrocodeHdrLoader: resd 1
+ .MicrocodeHdrFlags: resd 1
+ .MicrocodeHdrDataSize: resd 1
+ .MicrocodeHdrTotalSize: resd 1
+ .MicrocodeHdrRsvd: resd 3
+ .size:
+endstruc
+
+struc ExtSigHdr
+ .ExtSigHdrCount: resd 1
+ .ExtSigHdrChecksum: resd 1
+ .ExtSigHdrRsvd: resd 3
+ .size:
+endstruc
+
+struc ExtSig
+ .ExtSigProcessor: resd 1
+ .ExtSigFlags: resd 1
+ .ExtSigChecksum: resd 1
+ .size:
+endstruc
+
+struc LoadMicrocodeParams
+ ; FSP_UPD_HEADER {
+ .FspUpdHeader: resd 8
+ ; }
+ ; FSPT_CORE_UPD {
+ .MicrocodeCodeAddr: resd 1
+ .MicrocodeCodeSize: resd 1
+ .CodeRegionBase: resd 1
+ .CodeRegionSize: resd 1
+ ; }
+ .size:
+endstruc
+
+struc LoadMicrocodeParamsFsp22
+ ; FSP_UPD_HEADER {
+ .FspUpdHeaderSignature: resd 2
+ .FspUpdHeaderRevision: resb 1
+ .FspUpdHeaderReserved: resb 23
+ ; }
+ ; FSPT_ARCH_UPD{
+ .FsptArchUpd: resd 8
+ ; }
+ ; FSPT_CORE_UPD {
+ .MicrocodeCodeAddr: resd 1
+ .MicrocodeCodeSize: resd 1
+ .CodeRegionBase: resd 1
+ .CodeRegionSize: resd 1
+ ; }
+ .size:
+endstruc
+
+;
+; Define SSE macros
+;
+;
+;args 1: ReturnAddress 2:MmxRegister
+;
+%macro LOAD_MMX_EXT 2
+ mov esi, %1
+ movd %2, esi ; save ReturnAddress into MMX
+%endmacro
+
+;
+;args 1: RoutineLabel 2:MmxRegister
+;
+%macro CALL_MMX_EXT 2
+ mov esi, %%ReturnAddress
+ movd %2, esi ; save ReturnAddress into MMX
+ jmp %1
+%%ReturnAddress:
+%endmacro
+
+;
+;arg 1:MmxRegister
+;
+%macro RET_ESI_EXT 1
+ movd esi, %1 ; move ReturnAddress from MMX to ESI
+ jmp esi
+%endmacro
+
+;
+;arg 1:RoutineLabel
+;
+%macro CALL_MMX 1
+ CALL_MMX_EXT %1, mm7
+%endmacro
+
+%macro RET_ESI 0
+ RET_ESI_EXT mm7
+%endmacro
+
+;
+; @todo: The strong/weak implementation does not work.
+; This needs to be reviewed later.
+;
+;------------------------------------------------------------------------------
+;
+;;global ASM_PFX(SecPlatformInitDefault)
+;ASM_PFX(SecPlatformInitDefault):
+; ; Inputs:
+; ; mm7 -> Return address
+; ; Outputs:
+; ; eax -> 0 - Successful, Non-zero - Failed.
+; ; Register Usage:
+; ; eax is cleared and ebp is used for return address.
+; ; All others reserved.
+;
+; ; Save return address to EBP
+; movd ebp, mm7
+;
+; xor eax, eax
+;Exit1:
+; jmp ebp
+
+;------------------------------------------------------------------------------
+global ASM_PFX(LoadMicrocodeDefault)
+ASM_PFX(LoadMicrocodeDefault):
+ ; Inputs:
+ ; esp -> LoadMicrocodeParams pointer
+ ; Register Usage:
+ ; esp Preserved
+ ; All others destroyed
+ ; Assumptions:
+ ; No memory available, stack is hard-coded and used for return address
+ ; Executed by SBSP and NBSP
+ ; Beginning of microcode update region starts on paragraph boundary
+
+ ;
+ ;
+ ; Save return address to EBP
+ movd ebp, mm7
+
+ cmp esp, 0
+ jz ParamError
+ mov eax, dword [esp + 4] ; Parameter pointer
+ cmp eax, 0
+ jz ParamError
+ mov esp, eax
+
+ ; skip loading Microcode if the MicrocodeCodeSize is zero
+ ; and report error if size is less than 2k
+ ; first check UPD header revision
+ cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
+ jae Fsp22UpdHeader
+
+ ; UPD structure is compliant with FSP spec 2.0/2.1
+ mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
+ cmp eax, 0
+ jz Exit2
+ cmp eax, 0800h
+ jl ParamError
+
+ mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
+ cmp esi, 0
+ jnz CheckMainHeader
+ jmp ParamError
+
+Fsp22UpdHeader:
+ ; UPD structure is compliant with FSP spec 2.2
+ mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
+ cmp eax, 0
+ jz Exit2
+ cmp eax, 0800h
+ jl ParamError
+
+ mov esi, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
+ cmp esi, 0
+ jnz CheckMainHeader
+
+ParamError:
+ mov eax, 080000002h
+ jmp Exit2
+
+CheckMainHeader:
+ ; Get processor signature and platform ID from the installed processor
+ ; and save into registers for later use
+ ; ebx = processor signature
+ ; edx = platform ID
+ mov eax, 1
+ cpuid
+ mov ebx, eax
+ mov ecx, MSR_IA32_PLATFORM_ID
+ rdmsr
+ mov ecx, edx
+ shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
+ and ecx, 7h ; platform id at bit[52..50]
+ mov edx, 1
+ shl edx, cl
+
+ ; Current register usage
+ ; esp -> stack with parameters
+ ; esi -> microcode update to check
+ ; ebx = processor signature
+ ; edx = platform ID
+
+ ; Check for valid microcode header
+ ; Minimal test checking for header version and loader version as 1
+ mov eax, dword 1
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
+ jne AdvanceFixedSize
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
+ jne AdvanceFixedSize
+
+ ; Check if signature and plaform ID match
+ cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
+ jne LoadMicrocodeDefault1
+ test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
+ jnz LoadCheck ; Jif signature and platform ID match
+
+LoadMicrocodeDefault1:
+ ; Check if extended header exists
+ ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
+ xor eax, eax
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
+ je NextMicrocode
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
+ je NextMicrocode
+
+ ; Then verify total size - sizeof header > data size
+ mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
+ sub ecx, MicrocodeHdr.size
+ cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
+ jng NextMicrocode ; Jif extended header does not exist
+
+ ; Set edi -> extended header
+ mov edi, esi
+ add edi, MicrocodeHdr.size
+ add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
+
+ ; Get count of extended structures
+ mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
+
+ ; Move pointer to first signature structure
+ add edi, ExtSigHdr.size
+
+CheckExtSig:
+ ; Check if extended signature and platform ID match
+ cmp dword [edi + ExtSig.ExtSigProcessor], ebx
+ jne LoadMicrocodeDefault2
+ test dword [edi + ExtSig.ExtSigFlags], edx
+ jnz LoadCheck ; Jif signature and platform ID match
+LoadMicrocodeDefault2:
+ ; Check if any more extended signatures exist
+ add edi, ExtSig.size
+ loop CheckExtSig
+
+NextMicrocode:
+ ; Advance just after end of this microcode
+ xor eax, eax
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
+ je LoadMicrocodeDefault3
+ add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
+ jmp CheckAddress
+LoadMicrocodeDefault3:
+ add esi, dword 2048
+ jmp CheckAddress
+
+AdvanceFixedSize:
+ ; Advance by 4X dwords
+ add esi, dword 1024
+
+CheckAddress:
+ ; Check UPD header revision
+ cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
+ jae Fsp22UpdHeader1
+
+ ; UPD structure is compliant with FSP spec 2.0/2.1
+ ; Is automatic size detection ?
+ mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
+ cmp eax, 0ffffffffh
+ jz LoadMicrocodeDefault4
+
+ ; Address >= microcode region address + microcode region size?
+ add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
+ cmp esi, eax
+ jae Done ;Jif address is outside of microcode region
+ jmp CheckMainHeader
+
+Fsp22UpdHeader1:
+ ; UPD structure is compliant with FSP spec 2.2
+ ; Is automatic size detection ?
+ mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
+ cmp eax, 0ffffffffh
+ jz LoadMicrocodeDefault4
+
+ ; Address >= microcode region address + microcode region size?
+ add eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
+ cmp esi, eax
+ jae Done ;Jif address is outside of microcode region
+ jmp CheckMainHeader
+
+LoadMicrocodeDefault4:
+ ; Is valid Microcode start point ?
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
+ jz Done
+
+LoadCheck:
+ ; Get the revision of the current microcode update loaded
+ mov ecx, MSR_IA32_BIOS_SIGN_ID
+ xor eax, eax ; Clear EAX
+ xor edx, edx ; Clear EDX
+ wrmsr ; Load 0 to MSR at 8Bh
+
+ mov eax, 1
+ cpuid
+ mov ecx, MSR_IA32_BIOS_SIGN_ID
+ rdmsr ; Get current microcode signature
+
+ ; Verify this microcode update is not already loaded
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
+ je Continue
+
+LoadMicrocode:
+ ; EAX contains the linear address of the start of the Update Data
+ ; EDX contains zero
+ ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
+ ; Start microcode load with wrmsr
+ mov eax, esi
+ add eax, MicrocodeHdr.size
+ xor edx, edx
+ mov ecx, MSR_IA32_BIOS_UPDT_TRIG
+ wrmsr
+ mov eax, 1
+ cpuid
+
+Continue:
+ jmp NextMicrocode
+
+Done:
+ mov eax, 1
+ cpuid
+ mov ecx, MSR_IA32_BIOS_SIGN_ID
+ rdmsr ; Get current microcode signature
+ xor eax, eax
+ cmp edx, 0
+ jnz Exit2
+ mov eax, 08000000Eh
+
+Exit2:
+ jmp ebp
+
+
+global ASM_PFX(EstablishStackFsp)
+ASM_PFX(EstablishStackFsp):
+ ;
+ ; Save parameter pointer in edx
+ ;
+ mov edx, dword [esp + 4]
+
+ ;
+ ; Enable FSP STACK
+ ;
+ mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
+ add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
+
+ push DATA_LEN_OF_MCUD ; Size of the data region
+ push 4455434Dh ; Signature of the data region 'MCUD'
+
+ ; check UPD structure revision (edx + 8)
+ cmp byte [edx + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
+ jae Fsp22UpdHeader2
+
+ ; UPD structure is compliant with FSP spec 2.0/2.1
+ push dword [edx + LoadMicrocodeParams.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
+ push dword [edx + LoadMicrocodeParams.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
+ push dword [edx + LoadMicrocodeParams.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
+ push dword [edx + LoadMicrocodeParams.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
+ jmp ContinueAfterUpdPush
+
+Fsp22UpdHeader2:
+ ; UPD structure is compliant with FSP spec 2.2
+ push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
+ push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
+ push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
+ push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
+
+ContinueAfterUpdPush:
+ ;
+ ; Save API entry/exit timestamp into stack
+ ;
+ push DATA_LEN_OF_PER0 ; Size of the data region
+ push 30524550h ; Signature of the data region 'PER0'
+ rdtsc
+ push edx
+ push eax
+ LOAD_EDX
+ push edx
+ LOAD_EAX
+ push eax
+
+ ;
+ ; Terminator for the data on stack
+ ;
+ push 0
+
+ ;
+ ; Set ECX/EDX to the BootLoader temporary memory range
+ ;
+ mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
+ mov edx, ecx
+ add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
+ sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
+
+ cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
+ jb EstablishStackFspSuccess
+ mov eax, 80000003h ;EFI_UNSUPPORTED
+ jmp EstablishStackFspExit
+EstablishStackFspSuccess:
+ xor eax, eax
+
+EstablishStackFspExit:
+ RET_ESI
+
+;----------------------------------------------------------------------------
+; TempRamInit API
+;
+; This FSP API will load the microcode update, enable code caching for the
+; region specified by the boot loader and also setup a temporary stack to be
+; used till main memory is initialized.
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(TempRamInitApi)
+ASM_PFX(TempRamInitApi):
+ ;
+ ; Ensure SSE is enabled
+ ;
+ ENABLE_SSE
+
+ ;
+ ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
+ ;
+ SAVE_REGS
+
+ ;
+ ; Save timestamp into XMM6
+ ;
+ rdtsc
+ SAVE_EAX
+ SAVE_EDX
+
+ ;
+ ; Check Parameter
+ ;
+ mov eax, dword [esp + 4]
+ cmp eax, 0
+ mov eax, 80000002h
+ jz TempRamInitExit
+
+ ;
+ ; Sec Platform Init
+ ;
+ CALL_MMX ASM_PFX(SecPlatformInit)
+ cmp eax, 0
+ jnz TempRamInitExit
+
+ ; Load microcode
+ LOAD_ESP
+ CALL_MMX ASM_PFX(LoadMicrocodeDefault)
+ SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
+ ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
+
+ ; Call Sec CAR Init
+ LOAD_ESP
+ CALL_MMX ASM_PFX(SecCarInit)
+ cmp eax, 0
+ jnz TempRamInitExit
+
+ LOAD_ESP
+ CALL_MMX ASM_PFX(EstablishStackFsp)
+ cmp eax, 0
+ jnz TempRamInitExit
+
+ LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
+
+TempRamInitExit:
+ mov bl, al ; save al data in bl
+ mov al, 07Fh ; API exit postcode 7f
+ out 080h, al
+ mov al, bl ; restore al data from bl
+
+ ;
+ ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
+ ;
+ LOAD_REGS
+ ret
+
+;----------------------------------------------------------------------------
+; Module Entrypoint API
+;----------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ jmp $
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm
new file mode 100644
index 00000000..461c0bfb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm
@@ -0,0 +1,35 @@
+;; @file
+; Provide FSP helper function.
+;
+; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+ SECTION .text
+
+global ASM_PFX(FspInfoHeaderRelativeOff)
+ASM_PFX(FspInfoHeaderRelativeOff):
+ DD 0x12345678 ; This value must be patched by the build script
+
+global ASM_PFX(AsmGetFspBaseAddress)
+ASM_PFX(AsmGetFspBaseAddress):
+ call ASM_PFX(AsmGetFspInfoHeader)
+ add eax, 0x1C
+ mov eax, dword [eax]
+ ret
+
+global ASM_PFX(AsmGetFspInfoHeader)
+ASM_PFX(AsmGetFspInfoHeader):
+ call ASM_PFX(NextInstruction)
+ASM_PFX(NextInstruction):
+ pop eax
+ sub eax, ASM_PFX(NextInstruction)
+ add eax, ASM_PFX(AsmGetFspInfoHeader)
+ sub eax, dword [eax - ASM_PFX(AsmGetFspInfoHeader) + ASM_PFX(FspInfoHeaderRelativeOff)]
+ ret
+
+global ASM_PFX(AsmGetFspInfoHeaderNoStack)
+ASM_PFX(AsmGetFspInfoHeaderNoStack):
+ mov eax, ASM_PFX(AsmGetFspInfoHeader)
+ sub eax, dword [ASM_PFX(FspInfoHeaderRelativeOff)]
+ jmp edi
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/MicrocodeLoadNasm.inc b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/MicrocodeLoadNasm.inc
new file mode 100644
index 00000000..2b53f5d9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/MicrocodeLoadNasm.inc
@@ -0,0 +1,10 @@
+;; @file
+;
+;@copyright
+; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+MSR_IA32_PLATFORM_ID equ 000000017h
+MSR_IA32_BIOS_UPDT_TRIG equ 000000079h
+MSR_IA32_BIOS_SIGN_ID equ 00000008bh \ No newline at end of file
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/ReadEsp.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/ReadEsp.nasm
new file mode 100644
index 00000000..e407435a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/ReadEsp.nasm
@@ -0,0 +1,22 @@
+;; @file
+; Provide read ESP function
+;
+; Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+;------------------------------------------------------------------------------
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; UINT32
+; EFIAPI
+; AsmReadEsp (
+; VOID
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(AsmReadEsp)
+ASM_PFX(AsmReadEsp):
+ mov eax, esp
+ ret
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/SaveRestoreSseNasm.inc b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/SaveRestoreSseNasm.inc
new file mode 100644
index 00000000..1177e070
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/SaveRestoreSseNasm.inc
@@ -0,0 +1,181 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Abstract:
+;
+; Provide macro for register save/restore using SSE registers
+;
+;------------------------------------------------------------------------------
+
+;
+; Define SSE instruction set
+;
+%ifdef USE_SSE41_FLAG
+;
+; Define SSE macros using SSE 4.1 instructions
+; args 1:XMM, 2:IDX, 3:REG
+%macro SXMMN 3
+ pinsrd %1, %3, (%2 & 3)
+ %endmacro
+
+;
+;args 1:XMM, 2:REG, 3:IDX
+;
+%macro LXMMN 3
+ pextrd %2, %1, (%3 & 3)
+ %endmacro
+%else
+;
+; Define SSE macros using SSE 2 instructions
+; args 1:XMM, 2:IDX, 3:REG
+%macro SXMMN 3
+ pinsrw %1, %3, (%2 & 3) * 2
+ ror %3, 16
+ pinsrw %1, %3, (%2 & 3) * 2 + 1
+ rol %3, 16
+ %endmacro
+
+;
+;args 1:XMM, 2:REG, 3:IDX
+;
+%macro LXMMN 3
+ pshufd %1, %1, ((0E4E4E4h >> (%3 * 2)) & 0FFh)
+ movd %2, %1
+ pshufd %1, %1, ((0E4E4E4h >> (%3 * 2 + (%3 & 1) * 4)) & 0FFh)
+ %endmacro
+%endif
+
+;
+; XMM7 to save/restore EBP, EBX, ESI, EDI
+;
+%macro SAVE_REGS 0
+ SXMMN xmm7, 0, ebp
+ SXMMN xmm7, 1, ebx
+ SXMMN xmm7, 2, esi
+ SXMMN xmm7, 3, edi
+ SAVE_ESP
+ %endmacro
+
+%macro LOAD_REGS 0
+ LXMMN xmm7, ebp, 0
+ LXMMN xmm7, ebx, 1
+ LXMMN xmm7, esi, 2
+ LXMMN xmm7, edi, 3
+ LOAD_ESP
+ %endmacro
+
+;
+; XMM6 to save/restore EAX, EDX, ECX, ESP
+;
+%macro LOAD_EAX 0
+ LXMMN xmm6, eax, 1
+ %endmacro
+
+%macro SAVE_EAX 0
+ SXMMN xmm6, 1, eax
+ %endmacro
+
+%macro LOAD_EDX 0
+ LXMMN xmm6, edx, 2
+ %endmacro
+
+%macro SAVE_EDX 0
+ SXMMN xmm6, 2, edx
+ %endmacro
+
+%macro SAVE_ECX 0
+ SXMMN xmm6, 3, ecx
+ %endmacro
+
+%macro LOAD_ECX 0
+ LXMMN xmm6, ecx, 3
+ %endmacro
+
+%macro SAVE_ESP 0
+ SXMMN xmm6, 0, esp
+ %endmacro
+
+%macro LOAD_ESP 0
+ movd esp, xmm6
+ %endmacro
+;
+; XMM5 for calling stack
+; arg 1:Entry
+%macro CALL_XMM 1
+ mov esi, %%ReturnAddress
+ pslldq xmm5, 4
+%ifdef USE_SSE41_FLAG
+ pinsrd xmm5, esi, 0
+%else
+ pinsrw xmm5, esi, 0
+ ror esi, 16
+ pinsrw xmm5, esi, 1
+%endif
+ mov esi, %1
+ jmp esi
+%%ReturnAddress:
+ %endmacro
+
+%macro RET_XMM 0
+ movd esi, xmm5
+ psrldq xmm5, 4
+ jmp esi
+ %endmacro
+
+%macro ENABLE_SSE 0
+ ;
+ ; Initialize floating point units
+ ;
+ jmp NextAddress
+align 4
+ ;
+ ; Float control word initial value:
+ ; all exceptions masked, double-precision, round-to-nearest
+ ;
+FpuControlWord DW 027Fh
+ ;
+ ; Multimedia-extensions control word:
+ ; all exceptions masked, round-to-nearest, flush to zero for masked underflow
+ ;
+MmxControlWord DD 01F80h
+SseError:
+ ;
+ ; Processor has to support SSE
+ ;
+ jmp SseError
+NextAddress:
+ finit
+ fldcw [FpuControlWord]
+
+ ;
+ ; Use CpuId instruction (CPUID.01H:EDX.SSE[bit 25] = 1) to test
+ ; whether the processor supports SSE instruction.
+ ;
+ mov eax, 1
+ cpuid
+ bt edx, 25
+ jnc SseError
+
+%ifdef USE_SSE41_FLAG
+ ;
+ ; SSE 4.1 support
+ ;
+ bt ecx, 19
+ jnc SseError
+%endif
+
+ ;
+ ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
+ ;
+ mov eax, cr4
+ or eax, 00000600h
+ mov cr4, eax
+
+ ;
+ ; The processor should support SSE instruction and we can use
+ ; ldmxcsr instruction
+ ;
+ ldmxcsr [MmxControlWord]
+ %endmacro
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/Stack.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/Stack.nasm
new file mode 100644
index 00000000..a0fa9a20
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/Stack.nasm
@@ -0,0 +1,72 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2015 - 2019, 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 PermenentMemoryBase
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(SecSwitchStack)
+ASM_PFX(SecSwitchStack):
+ ;
+ ; Save three register: eax, ebx, ecx
+ ;
+ 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/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFsp.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFsp.c
new file mode 100644
index 00000000..bee6d3c5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFsp.c
@@ -0,0 +1,218 @@
+/** @file
+
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SecFsp.h"
+
+/**
+
+ Calculate the FSP IDT gate descriptor.
+
+ @param[in] IdtEntryTemplate IDT gate descriptor template.
+
+ @return FSP specific IDT gate descriptor.
+
+**/
+UINT64
+FspGetExceptionHandler(
+ IN UINT64 IdtEntryTemplate
+ )
+{
+ UINT32 Entry;
+ UINT64 ExceptionHandler;
+ IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor;
+ FSP_INFO_HEADER *FspInfoHeader;
+
+ FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader();
+ ExceptionHandler = IdtEntryTemplate;
+ IdtGateDescriptor = (IA32_IDT_GATE_DESCRIPTOR *)&ExceptionHandler;
+ Entry = (IdtGateDescriptor->Bits.OffsetHigh << 16) | IdtGateDescriptor->Bits.OffsetLow;
+ Entry = FspInfoHeader->ImageBase + FspInfoHeader->ImageSize - (~Entry + 1);
+ IdtGateDescriptor->Bits.OffsetHigh = (UINT16)(Entry >> 16);
+ IdtGateDescriptor->Bits.OffsetLow = (UINT16)Entry;
+
+ return ExceptionHandler;
+}
+
+/**
+ This interface fills platform specific data.
+
+ @param[in,out] FspData Pointer to the FSP global data.
+
+**/
+VOID
+EFIAPI
+SecGetPlatformData (
+ IN OUT FSP_GLOBAL_DATA *FspData
+ )
+{
+ FSP_PLAT_DATA *FspPlatformData;
+ UINT32 TopOfCar;
+ UINT32 *StackPtr;
+ UINT32 DwordSize;
+
+ FspPlatformData = &FspData->PlatformData;
+
+ //
+ // The entries of platform information, together with the number of them,
+ // reside in the bottom of stack, left untouched by normal stack operation.
+ //
+
+ FspPlatformData->DataPtr = NULL;
+ FspPlatformData->MicrocodeRegionBase = 0;
+ FspPlatformData->MicrocodeRegionSize = 0;
+ FspPlatformData->CodeRegionBase = 0;
+ FspPlatformData->CodeRegionSize = 0;
+
+ //
+ // Pointer to the size field
+ //
+ TopOfCar = PcdGet32(PcdTemporaryRamBase) + PcdGet32(PcdTemporaryRamSize);
+ StackPtr = (UINT32 *)(TopOfCar - sizeof (UINT32));
+
+ if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) {
+ while (*StackPtr != 0) {
+ if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) {
+ //
+ // This following data was pushed onto stack after TempRamInit API
+ //
+ DwordSize = 4;
+ StackPtr = StackPtr - 1 - DwordSize;
+ CopyMem (&(FspPlatformData->MicrocodeRegionBase), StackPtr, (DwordSize << 2));
+ StackPtr--;
+ } else if (*(StackPtr - 1) == FSP_PER0_SIGNATURE) {
+ //
+ // This is the performance data for InitTempMemory API entry/exit
+ //
+ DwordSize = 4;
+ StackPtr = StackPtr - 1 - DwordSize;
+ CopyMem (FspData->PerfData, StackPtr, (DwordSize << 2));
+
+ ((UINT8 *)(&FspData->PerfData[0]))[7] = FSP_PERF_ID_API_TEMP_RAM_INIT_ENTRY;
+ ((UINT8 *)(&FspData->PerfData[1]))[7] = FSP_PERF_ID_API_TEMP_RAM_INIT_EXIT;
+
+ StackPtr--;
+ } else {
+ StackPtr -= (*StackPtr);
+ }
+ }
+ }
+}
+
+/**
+
+ Initialize the FSP global data region.
+ It needs to be done as soon as possible after the stack is setup.
+
+ @param[in,out] PeiFspData Pointer of the FSP global data.
+ @param[in] BootLoaderStack BootLoader stack.
+ @param[in] ApiIdx The index of the FSP API.
+
+**/
+VOID
+FspGlobalDataInit (
+ IN OUT FSP_GLOBAL_DATA *PeiFspData,
+ IN UINT32 BootLoaderStack,
+ IN UINT8 ApiIdx
+ )
+{
+ VOID *FspmUpdDataPtr;
+ CHAR8 ImageId[9];
+ UINTN Idx;
+
+ //
+ // Set FSP Global Data pointer
+ //
+ SetFspGlobalDataPointer (PeiFspData);
+ ZeroMem ((VOID *)PeiFspData, sizeof(FSP_GLOBAL_DATA));
+
+ PeiFspData->Signature = FSP_GLOBAL_DATA_SIGNATURE;
+ PeiFspData->Version = 0;
+ PeiFspData->CoreStack = BootLoaderStack;
+ PeiFspData->PerfIdx = 2;
+ PeiFspData->PerfSig = FSP_PERFORMANCE_DATA_SIGNATURE;
+
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_ENTRY);
+
+ //
+ // Get FSP Header offset
+ // It may have multiple FVs, so look into the last one for FSP header
+ //
+ PeiFspData->FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader();
+ SecGetPlatformData (PeiFspData);
+
+ //
+ // Set API calling mode
+ //
+ SetFspApiCallingIndex (ApiIdx);
+
+ //
+ // Set UPD pointer
+ //
+ FspmUpdDataPtr = (VOID *) GetFspApiParameter ();
+ if (FspmUpdDataPtr == NULL) {
+ FspmUpdDataPtr = (VOID *)(PeiFspData->FspInfoHeader->ImageBase + PeiFspData->FspInfoHeader->CfgRegionOffset);
+ }
+ SetFspUpdDataPointer (FspmUpdDataPtr);
+ SetFspMemoryInitUpdDataPointer (FspmUpdDataPtr);
+ SetFspSiliconInitUpdDataPointer (NULL);
+
+ //
+ // Initialize OnSeparateStack value.
+ //
+ if (PcdGet8 (PcdFspHeapSizePercentage) != 0) {
+ //
+ // FSP is running on its own stack and may need switching stack when calling bootloader functions.
+ //
+ GetFspGlobalDataPointer ()->OnSeparateStack = 1;
+ }
+
+ //
+ // Initialize serial port
+ // It might have been done in ProcessLibraryConstructorList(), however,
+ // the FSP global data is not initialized at that time. So do it again
+ // for safe.
+ //
+ SerialPortInitialize ();
+
+ //
+ // Ensure the global data pointer is valid
+ //
+ ASSERT (GetFspGlobalDataPointer () == PeiFspData);
+
+ for (Idx = 0; Idx < 8; Idx++) {
+ ImageId[Idx] = PeiFspData->FspInfoHeader->ImageId[Idx];
+ }
+ ImageId[Idx] = 0;
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "\n============= FSP Spec v%d.%d Header Revision v%x (%a v%x.%x.%x.%x) =============\n", \
+ (PeiFspData->FspInfoHeader->SpecVersion >> 4) & 0xF, \
+ PeiFspData->FspInfoHeader->SpecVersion & 0xF, \
+ PeiFspData->FspInfoHeader->HeaderRevision, \
+ ImageId, \
+ (PeiFspData->FspInfoHeader->ImageRevision >> 24) & 0xFF, \
+ (PeiFspData->FspInfoHeader->ImageRevision >> 16) & 0xFF, \
+ (PeiFspData->FspInfoHeader->ImageRevision >> 8) & 0xFF, \
+ PeiFspData->FspInfoHeader->ImageRevision & 0xFF));
+}
+
+/**
+
+ Adjust the FSP data pointers after the stack is migrated to memory.
+
+ @param[in] OffsetGap The offset gap between the old stack and the new stack.
+
+**/
+VOID
+FspDataPointerFixUp (
+ IN UINT32 OffsetGap
+ )
+{
+ FSP_GLOBAL_DATA *NewFspData;
+
+ NewFspData = (FSP_GLOBAL_DATA *)((UINTN)GetFspGlobalDataPointer() + (UINTN)OffsetGap);
+ SetFspGlobalDataPointer (NewFspData);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFsp.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFsp.h
new file mode 100644
index 00000000..68ac9d2f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFsp.h
@@ -0,0 +1,93 @@
+/** @file
+
+ Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SEC_FSP_H_
+#define _SEC_FSP_H_
+
+#include <PiPei.h>
+#include <FspEas.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/FspCommonLib.h>
+#include <Library/FspSecPlatformLib.h>
+
+#define FSP_MCUD_SIGNATURE SIGNATURE_32 ('M', 'C', 'U', 'D')
+#define FSP_PER0_SIGNATURE SIGNATURE_32 ('P', 'E', 'R', '0')
+
+/**
+
+ Calculate the FSP IDT gate descriptor.
+
+ @param[in] IdtEntryTemplate IDT gate descriptor template.
+
+ @return FSP specific IDT gate descriptor.
+
+**/
+UINT64
+FspGetExceptionHandler(
+ IN UINT64 IdtEntryTemplate
+ );
+
+/**
+
+ Initialize the FSP global data region.
+ It needs to be done as soon as possible after the stack is setup.
+
+ @param[in,out] PeiFspData Pointer of the FSP global data.
+ @param[in] BootLoaderStack BootLoader stack.
+ @param[in] ApiIdx The index of the FSP API.
+
+**/
+VOID
+FspGlobalDataInit (
+ IN OUT FSP_GLOBAL_DATA *PeiFspData,
+ IN UINT32 BootLoaderStack,
+ IN UINT8 ApiIdx
+ );
+
+
+/**
+
+ Adjust the FSP data pointers after the stack is migrated to memory.
+
+ @param[in] OffsetGap The offset gap between the old stack and the new stack.
+
+**/
+VOID
+FspDataPointerFixUp (
+ IN UINT32 OffsetGap
+ );
+
+
+/**
+ This interface returns the base address of FSP binary.
+
+ @return FSP binary base address.
+
+**/
+UINT32
+EFIAPI
+AsmGetFspBaseAddress (
+ VOID
+ );
+
+/**
+ This interface gets FspInfoHeader pointer
+
+ @return FSP binary base address.
+
+**/
+UINT32
+EFIAPI
+AsmGetFspInfoHeader (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c
new file mode 100644
index 00000000..06044f9e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c
@@ -0,0 +1,91 @@
+/** @file
+
+ Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SecFsp.h"
+
+
+/**
+ This function check the FSP API calling condition.
+
+ @param[in] ApiIdx Internal index of the FSP API.
+ @param[in] ApiParam Parameter of the FSP API.
+
+**/
+EFI_STATUS
+EFIAPI
+FspApiCallingCheck (
+ IN UINT8 ApiIdx,
+ IN VOID *ApiParam
+ )
+{
+ EFI_STATUS Status;
+ FSP_GLOBAL_DATA *FspData;
+
+ Status = EFI_SUCCESS;
+ FspData = GetFspGlobalDataPointer ();
+
+ if (ApiIdx == NotifyPhaseApiIndex) {
+ //
+ // NotifyPhase check
+ //
+ if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+ } else if (ApiIdx == FspMemoryInitApiIndex) {
+ //
+ // FspMemoryInit check
+ //
+ if ((UINT32)FspData != 0xFFFFFFFF) {
+ Status = EFI_UNSUPPORTED;
+ } else if (EFI_ERROR (FspUpdSignatureCheck (ApiIdx, ApiParam))) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (ApiIdx == TempRamExitApiIndex) {
+ //
+ // TempRamExit check
+ //
+ if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+ } else if ((ApiIdx == FspSiliconInitApiIndex) || (ApiIdx == FspMultiPhaseSiInitApiIndex)) {
+ //
+ // FspSiliconInit check
+ //
+ if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
+ Status = EFI_UNSUPPORTED;
+ } else if (EFI_ERROR (FspUpdSignatureCheck (FspSiliconInitApiIndex, ApiParam))) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ if ((ApiIdx != FspMemoryInitApiIndex)) {
+ //
+ // For FspMemoryInit, the global data is not valid yet
+ // The API index will be updated by SecCore after the global data
+ // is initialized
+ //
+ SetFspApiCallingIndex (ApiIdx);
+ }
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.c
new file mode 100644
index 00000000..1d102fca
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.c
@@ -0,0 +1,301 @@
+/** @file
+
+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SecMain.h"
+#include "SecFsp.h"
+
+EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
+ SecTemporaryRamSupport
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI,
+ &gFspInApiModePpiGuid,
+ NULL
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamSupportPpiGuid,
+ &gSecTemporaryRamSupportPpi
+ }
+};
+
+//
+// These are IDT entries pointing to 08:FFFFFFE4h.
+//
+UINT64 mIdtEntryTemplate = 0xffff8e000008ffe4ULL;
+
+/**
+
+ 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[in] SizeOfRam Size of the temporary memory available for use.
+ @param[in] TempRamBase Base address of temporary ram
+ @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume.
+ @param[in] PeiCore PeiCore entry point.
+ @param[in] BootLoaderStack BootLoader stack.
+ @param[in] ApiIdx the index of API.
+
+ @return This function never returns.
+
+**/
+VOID
+EFIAPI
+SecStartup (
+ IN UINT32 SizeOfRam,
+ IN UINT32 TempRamBase,
+ IN VOID *BootFirmwareVolume,
+ IN PEI_CORE_ENTRY PeiCore,
+ IN UINT32 BootLoaderStack,
+ IN UINT32 ApiIdx
+ )
+{
+ EFI_SEC_PEI_HAND_OFF SecCoreData;
+ IA32_DESCRIPTOR IdtDescriptor;
+ SEC_IDT_TABLE IdtTableInStack;
+ UINT32 Index;
+ FSP_GLOBAL_DATA PeiFspData;
+ UINT64 ExceptionHandler;
+ UINTN IdtSize;
+
+ //
+ // Process all libraries constructor function linked to SecCore.
+ //
+ ProcessLibraryConstructorList ();
+
+ //
+ // Initialize floating point operating environment
+ // to be compliant with UEFI spec.
+ //
+ InitializeFloatingPointUnits ();
+
+ //
+ // Scenario 1 memory map when running on bootloader stack
+ //
+ // |-------------------|---->
+ // |Idt Table |
+ // |-------------------|
+ // |PeiService Pointer |
+ // |-------------------|
+ // | |
+ // | |
+ // | Heap |
+ // | |
+ // | |
+ // |-------------------|----> TempRamBase
+ //
+ //
+ // |-------------------|
+ // |Bootloader stack |----> somewhere in memory, FSP will share this stack.
+ // |-------------------|
+
+ //
+ // Scenario 2 memory map when running FSP on a separate stack
+ //
+ // |-------------------|---->
+ // |Idt Table |
+ // |-------------------|
+ // |PeiService Pointer | PeiStackSize
+ // |-------------------|
+ // | |
+ // | Stack |
+ // |-------------------|---->
+ // | |
+ // | |
+ // | Heap | PeiTemporaryRamSize
+ // | |
+ // | |
+ // |-------------------|----> TempRamBase
+ IdtTableInStack.PeiService = 0;
+ AsmReadIdtr (&IdtDescriptor);
+ if (IdtDescriptor.Base == 0) {
+ ExceptionHandler = FspGetExceptionHandler(mIdtEntryTemplate);
+ for (Index = 0; Index < FixedPcdGet8(PcdFspMaxInterruptSupported); Index ++) {
+ CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&ExceptionHandler, sizeof (UINT64));
+ }
+ IdtSize = sizeof (IdtTableInStack.IdtTable);
+ } else {
+ IdtSize = IdtDescriptor.Limit + 1;
+ if (IdtSize > sizeof (IdtTableInStack.IdtTable)) {
+ //
+ // ERROR: IDT table size from boot loader is larger than FSP can support, DeadLoop here!
+ //
+ CpuDeadLoop();
+ } else {
+ CopyMem ((VOID *) (UINTN) &IdtTableInStack.IdtTable, (VOID *) IdtDescriptor.Base, IdtSize);
+ }
+ }
+ IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;
+ IdtDescriptor.Limit = (UINT16)(IdtSize - 1);
+
+ AsmWriteIdtr (&IdtDescriptor);
+
+ //
+ // Initialize the global FSP data region
+ //
+ FspGlobalDataInit (&PeiFspData, BootLoaderStack, (UINT8)ApiIdx);
+
+ //
+ // Update the base address and length of Pei temporary memory
+ //
+ SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
+ SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
+ SecCoreData.BootFirmwareVolumeSize = (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;
+
+ //
+ // Support FSP reserved temporary memory from the whole temporary memory provided by bootloader.
+ // FSP reserved temporary memory will not be given to PeiCore.
+ //
+ SecCoreData.TemporaryRamBase = (UINT8 *)(UINTN) TempRamBase + PcdGet32 (PcdFspPrivateTemporaryRamSize);
+ SecCoreData.TemporaryRamSize = SizeOfRam - PcdGet32 (PcdFspPrivateTemporaryRamSize);
+ if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
+ SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
+ SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize;
+ SecCoreData.StackBase = (VOID *)GetFspEntryStack(); // Share the same boot loader stack
+ SecCoreData.StackSize = 0;
+ } else {
+ SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
+ SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize * PcdGet8 (PcdFspHeapSizePercentage) / 100;
+ SecCoreData.StackBase = (VOID*)(UINTN)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize);
+ SecCoreData.StackSize = SecCoreData.TemporaryRamSize - SecCoreData.PeiTemporaryRamSize;
+ }
+
+ DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeBase - 0x%x\n", SecCoreData.BootFirmwareVolumeBase));
+ DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeSize - 0x%x\n", SecCoreData.BootFirmwareVolumeSize));
+ DEBUG ((DEBUG_INFO, "Fsp TemporaryRamBase - 0x%x\n", SecCoreData.TemporaryRamBase));
+ DEBUG ((DEBUG_INFO, "Fsp TemporaryRamSize - 0x%x\n", SecCoreData.TemporaryRamSize));
+ DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamBase - 0x%x\n", SecCoreData.PeiTemporaryRamBase));
+ DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamSize - 0x%x\n", SecCoreData.PeiTemporaryRamSize));
+ DEBUG ((DEBUG_INFO, "Fsp StackBase - 0x%x\n", SecCoreData.StackBase));
+ DEBUG ((DEBUG_INFO, "Fsp StackSize - 0x%x\n", SecCoreData.StackSize));
+
+ //
+ // Call PeiCore Entry
+ //
+ PeiCore (&SecCoreData, mPeiSecPlatformInformationPpi);
+
+ //
+ // Should never be here
+ //
+ CpuDeadLoop ();
+}
+
+/**
+ This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupport (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ )
+{
+ IA32_DESCRIPTOR IdtDescriptor;
+ VOID* OldHeap;
+ VOID* NewHeap;
+ VOID* OldStack;
+ VOID* NewStack;
+ UINTN HeapSize;
+ UINTN StackSize;
+
+ UINTN CurrentStack;
+ UINTN FspStackBase;
+
+ //
+ // Override OnSeparateStack to 1 because this function will switch stack to permanent memory
+ // which makes FSP running on different stack from bootloader temporary ram stack.
+ //
+ GetFspGlobalDataPointer ()->OnSeparateStack = 1;
+
+ if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
+
+ CurrentStack = AsmReadEsp();
+ FspStackBase = (UINTN)GetFspEntryStack();
+
+ StackSize = FspStackBase - CurrentStack;
+ HeapSize = CopySize;
+
+ OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
+ NewHeap = (VOID*)((UINTN)PermanentMemoryBase);
+
+ OldStack = (VOID*)CurrentStack;
+ //
+ //The old stack is copied at the end of the stack region because stack grows down.
+ //
+ NewStack = (VOID*)((UINTN)PermanentMemoryBase - StackSize);
+
+ } else {
+ HeapSize = CopySize * PcdGet8 (PcdFspHeapSizePercentage) / 100 ;
+ StackSize = CopySize - HeapSize;
+
+ OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
+ NewHeap = (VOID*)((UINTN)PermanentMemoryBase + StackSize);
+
+ OldStack = (VOID*)((UINTN)TemporaryMemoryBase + HeapSize);
+ NewStack = (VOID*)(UINTN)PermanentMemoryBase;
+
+ }
+ //
+ // Migrate Heap
+ //
+ CopyMem (NewHeap, OldHeap, HeapSize);
+
+ //
+ // Migrate Stack
+ //
+ CopyMem (NewStack, OldStack, StackSize);
+
+
+ //
+ // We need *not* fix the return address because currently,
+ // The PeiCore is executed in flash.
+ //
+
+ //
+ // Rebase IDT table in permanent memory
+ //
+ AsmReadIdtr (&IdtDescriptor);
+ IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
+
+ AsmWriteIdtr (&IdtDescriptor);
+
+ //
+ // Fixed the FSP data pointer
+ //
+ FspDataPointerFixUp ((UINTN)NewStack - (UINTN)OldStack);
+
+ //
+ // SecSwitchStack function must be invoked after the memory migration
+ // immediately, also we need fixup the stack change caused by new call into
+ // permanent memory.
+ //
+ SecSwitchStack (
+ (UINT32) (UINTN) OldStack,
+ (UINT32) (UINTN) NewStack
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.h
new file mode 100644
index 00000000..1487b846
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.h
@@ -0,0 +1,138 @@
+/** @file
+
+ Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SEC_CORE_H_
+#define _SEC_CORE_H_
+
+
+#include <PiPei.h>
+#include <Ppi/TemporaryRamSupport.h>
+
+#include <Library/BaseLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciCf8Lib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/FspSwitchStackLib.h>
+#include <Library/FspCommonLib.h>
+#include <Library/UefiCpuLib.h>
+#include <FspEas.h>
+
+typedef VOID (*PEI_CORE_ENTRY) ( \
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, \
+ IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList \
+);
+
+typedef struct _SEC_IDT_TABLE {
+ //
+ // Reserved 8 bytes preceding IDT to store EFI_PEI_SERVICES**, since IDT base
+ // address should be 8-byte alignment.
+ // Note: For IA32, only the 4 bytes immediately preceding IDT is used to store
+ // EFI_PEI_SERVICES**
+ //
+ UINT64 PeiService;
+ UINT64 IdtTable[FixedPcdGet8 (PcdFspMaxInterruptSupported)];
+} SEC_IDT_TABLE;
+
+/**
+ Switch the stack in the temporary memory to the one in the permanent memory.
+
+ This function must be invoked after the memory migration immediately. The relative
+ position of the stack in the temporary and permanent memory is same.
+
+ @param[in] TemporaryMemoryBase Base address of the temporary memory.
+ @param[in] PermenentMemoryBase Base address of the permanent memory.
+**/
+VOID
+EFIAPI
+SecSwitchStack (
+ IN UINT32 TemporaryMemoryBase,
+ IN UINT32 PermenentMemoryBase
+ );
+
+/**
+ This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param[in] CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupport (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+
+/**
+
+ 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[in] SizeOfRam Size of the temporary memory available for use.
+ @param[in] TempRamBase Base address of temporary ram
+ @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume.
+ @param[in] PeiCore PeiCore entry point.
+ @param[in] BootLoaderStack BootLoader stack.
+ @param[in] ApiIdx the index of API.
+
+ @return This function never returns.
+
+**/
+VOID
+EFIAPI
+SecStartup (
+ IN UINT32 SizeOfRam,
+ IN UINT32 TempRamBase,
+ IN VOID *BootFirmwareVolume,
+ IN PEI_CORE_ENTRY PeiCore,
+ IN UINT32 BootLoaderStack,
+ IN UINT32 ApiIdx
+ );
+
+/**
+ Autogenerated 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
+ );
+
+/**
+
+ Return value of esp.
+
+ @return value of esp.
+
+**/
+UINT32
+EFIAPI
+AsmReadEsp (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
new file mode 100644
index 00000000..2dc9f178
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
Binary files differ
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Build.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Build.py
new file mode 100755
index 00000000..fb1a25a0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Build.py
@@ -0,0 +1,47 @@
+## @file
+# Automate the process of building the various reset vector types
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+import glob
+import os
+import subprocess
+import sys
+
+def RunCommand(commandLine):
+ #print ' '.join(commandLine)
+ return subprocess.call(commandLine)
+
+for filename in glob.glob(os.path.join('Bin', '*.raw')):
+ os.remove(filename)
+
+arch = 'ia32'
+debugType = None
+output = os.path.join('Bin', 'ResetVec')
+output += '.' + arch
+if debugType is not None:
+ output += '.' + debugType
+output += '.raw'
+commandLine = (
+ 'nasm',
+ '-D', 'ARCH_%s' % arch.upper(),
+ '-D', 'DEBUG_%s' % str(debugType).upper(),
+ '-o', output,
+ 'ResetVectorCode.asm',
+ )
+ret = RunCommand(commandLine)
+print '\tASM\t' + output
+if ret != 0: sys.exit(ret)
+
+commandLine = (
+ 'python',
+ 'Tools/FixupForRawSection.py',
+ output,
+ )
+print '\tFIXUP\t' + output
+ret = RunCommand(commandLine)
+if ret != 0: sys.exit(ret)
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16 b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16
new file mode 100644
index 00000000..440d5ac1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16
@@ -0,0 +1,97 @@
+;; @file
+; Reset Vector Data structure
+; This structure is located at 0xFFFFFFC0
+;
+; Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;;
+
+BITS 16
+
+
+;
+; The layout of this file is fixed. The build tool makes assumption of the layout.
+;
+
+ORG 0x0
+;
+; Reserved
+;
+ReservedData: DD 0eeeeeeeeh, 0eeeeeeeeh
+
+ ; ORG 0x10
+ TIMES 0x10-($-$$) DB 0
+;
+; This is located at 0xFFFFFFD0h
+;
+ mov di, "AP"
+ jmp ApStartup
+
+ ; ORG 0x20
+
+ TIMES 0x20-($-$$) DB 0
+
+; Pointer to the entry point of the PEI core
+; It is located at 0xFFFFFFE0, and is fixed up by some build tool
+; So if the value 8..1 appears in the final FD image, tool failure occurs.
+;
+PeiCoreEntryPoint: DD 0x12345678
+
+;
+; This is the handler for all kinds of exceptions. Since it's for debugging
+; purpose only, nothing except a deadloop would be done here. Developers could
+; analyze the cause of the exception if a debugger had been attached.
+;
+InterruptHandler:
+ jmp $
+ iret
+
+ ; ORG 0x30
+ TIMES 0x30-($-$$) DB 0
+;
+; For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte
+; Execution starts here upon power-on/platform-reset.
+;
+ResetHandler:
+ nop
+ nop
+
+ApStartup:
+ ;
+ ; Jmp Rel16 instruction
+ ; Use machine code directly in case of the assembler optimization
+ ; SEC entry point relative address will be fixed up by some build tool.
+ ;
+ ; Typically, SEC entry point is the function _ModuleEntryPoint() defined in
+ ; SecEntry.asm
+ ;
+ DB 0x0e9
+ DW -3
+
+ ; ORG 0x38
+
+ TIMES 0x38-($-$$) DB 0
+;
+; Ap reset vector segment address is at 0xFFFFFFF8
+; This will be fixed up by some build tool,
+; so if the value 1..8 appears in the final FD image,
+; tool failure occurs
+;
+ApSegAddress: dd 0x12345678
+
+ ; ORG 0x3c
+ TIMES 0x3c-($-$$) DB 0
+;
+; BFV Base is at 0xFFFFFFFC
+; This will be fixed up by some build tool,
+; so if the value 1..8 appears in the final FD image,
+; tool failure occurs.
+;
+BfvBase: DD 0x12345678
+
+;
+; Nothing can go here, otherwise the layout of this file would change.
+;
+
+ ; END
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/ResetVectorCode.asm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/ResetVectorCode.asm
new file mode 100644
index 00000000..acd65bde
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/ResetVectorCode.asm
@@ -0,0 +1,11 @@
+;------------------------------------------------------------------------------
+; @file
+; This file includes all other code files to assemble the reset vector code
+;
+; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+
+%include "Ia16/ResetVec.asm16"
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py
new file mode 100755
index 00000000..5ddddb6b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py
@@ -0,0 +1,104 @@
+## @file
+# Apply fixup to VTF binary image for FFS Raw section
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+import sys
+
+filename = sys.argv[1]
+
+if filename.lower().find('ia32') >= 0:
+ d = open(sys.argv[1], 'rb').read()
+ c = ((len(d) + 4 + 7) & ~7) - 4
+ if c > len(d):
+ c -= len(d)
+ f = open(sys.argv[1], 'wb')
+ f.write('\x90' * c)
+ f.write(d)
+ f.close()
+else:
+ from struct import pack
+
+ PAGE_PRESENT = 0x01
+ PAGE_READ_WRITE = 0x02
+ PAGE_USER_SUPERVISOR = 0x04
+ PAGE_WRITE_THROUGH = 0x08
+ PAGE_CACHE_DISABLE = 0x010
+ PAGE_ACCESSED = 0x020
+ PAGE_DIRTY = 0x040
+ PAGE_PAT = 0x080
+ PAGE_GLOBAL = 0x0100
+ PAGE_2M_MBO = 0x080
+ PAGE_2M_PAT = 0x01000
+
+ def NopAlign4k(s):
+ c = ((len(s) + 0xfff) & ~0xfff) - len(s)
+ return ('\x90' * c) + s
+
+ def PageDirectoryEntries4GbOf2MbPages(baseAddress):
+
+ s = ''
+ for i in range(0x800):
+ i = (
+ baseAddress + long(i << 21) +
+ PAGE_2M_MBO +
+ PAGE_CACHE_DISABLE +
+ PAGE_ACCESSED +
+ PAGE_DIRTY +
+ PAGE_READ_WRITE +
+ PAGE_PRESENT
+ )
+ s += pack('Q', i)
+ return s
+
+ def PageDirectoryPointerTable4GbOf2MbPages(pdeBase):
+ s = ''
+ for i in range(0x200):
+ i = (
+ pdeBase +
+ (min(i, 3) << 12) +
+ PAGE_CACHE_DISABLE +
+ PAGE_ACCESSED +
+ PAGE_READ_WRITE +
+ PAGE_PRESENT
+ )
+ s += pack('Q', i)
+ return s
+
+ def PageMapLevel4Table4GbOf2MbPages(pdptBase):
+ s = ''
+ for i in range(0x200):
+ i = (
+ pdptBase +
+ (min(i, 0) << 12) +
+ PAGE_CACHE_DISABLE +
+ PAGE_ACCESSED +
+ PAGE_READ_WRITE +
+ PAGE_PRESENT
+ )
+ s += pack('Q', i)
+ return s
+
+ def First4GbPageEntries(topAddress):
+ PDE = PageDirectoryEntries4GbOf2MbPages(0L)
+ pml4tBase = topAddress - 0x1000
+ pdptBase = pml4tBase - 0x1000
+ pdeBase = pdptBase - len(PDE)
+ PDPT = PageDirectoryPointerTable4GbOf2MbPages(pdeBase)
+ PML4T = PageMapLevel4Table4GbOf2MbPages(pdptBase)
+ return PDE + PDPT + PML4T
+
+ def AlignAndAddPageTables():
+ d = open(sys.argv[1], 'rb').read()
+ code = NopAlign4k(d)
+ topAddress = 0x100000000 - len(code)
+ d = ('\x90' * 4) + First4GbPageEntries(topAddress) + code
+ f = open(sys.argv[1], 'wb')
+ f.write(d)
+ f.close()
+
+ AlignAndAddPageTables()
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas.h
new file mode 100644
index 00000000..d9268290
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas.h
@@ -0,0 +1,18 @@
+/** @file
+ Intel FSP definition from Intel Firmware Support Package External
+ Architecture Specification v2.0.
+
+ Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_EAS_H_
+#define _FSP_EAS_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Guid/GuidHobFspEas.h>
+#include <Guid/FspHeaderFile.h>
+#include <FspEas/FspApi.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas/FspApi.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas/FspApi.h
new file mode 100644
index 00000000..eb9ce861
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas/FspApi.h
@@ -0,0 +1,485 @@
+/** @file
+ Intel FSP API definition from Intel Firmware Support Package External
+ Architecture Specification v2.0 - v2.2
+
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_API_H_
+#define _FSP_API_H_
+
+#include <Pi/PiStatusCode.h>
+
+///
+/// FSP Reset Status code
+/// These are defined in FSP EAS v2.0 section 11.2.2 - OEM Status Code
+/// @{
+#define FSP_STATUS_RESET_REQUIRED_COLD 0x40000001
+#define FSP_STATUS_RESET_REQUIRED_WARM 0x40000002
+#define FSP_STATUS_RESET_REQUIRED_3 0x40000003
+#define FSP_STATUS_RESET_REQUIRED_4 0x40000004
+#define FSP_STATUS_RESET_REQUIRED_5 0x40000005
+#define FSP_STATUS_RESET_REQUIRED_6 0x40000006
+#define FSP_STATUS_RESET_REQUIRED_7 0x40000007
+#define FSP_STATUS_RESET_REQUIRED_8 0x40000008
+/// @}
+
+///
+/// FSP Event related definition.
+///
+#define FSP_EVENT_CODE 0xF5000000
+#define FSP_POST_CODE (FSP_EVENT_CODE | 0x00F80000)
+
+/*
+ FSP may optionally include the capability of generating events messages to aid in the debugging of firmware issues.
+ These events fall under three catagories: Error, Progress, and Debug. The event reporting mechanism follows the
+ status code services described in section 6 and 7 of the PI Specification v1.7 Volume 3.
+
+ @param[in] Type Indicates the type of event being reported.
+ See MdePkg/Include/Pi/PiStatusCode.h for the definition of EFI_STATUS_CODE_TYPE.
+ @param[in] Value Describes the current status of a hardware or software entity.
+ This includes information about the class and subclass that is used to classify the entity as well as an operation.
+ For progress events, the operation is the current activity. For error events, it is the exception.
+ For debug events, it is not defined at this time.
+ See MdePkg/Include/Pi/PiStatusCode.h for the definition of EFI_STATUS_CODE_VALUE.
+ @param[in] Instance The enumeration of a hardware or software entity within the system.
+ A system may contain multiple entities that match a class/subclass pairing. The instance differentiates between them.
+ An instance of 0 indicates that instance information is unavailable, not meaningful, or not relevant.
+ Valid instance numbers start with 1.
+ @param[in] *CallerId This parameter can be used to identify the sub-module within the FSP generating the event.
+ This parameter may be NULL.
+ @param[in] *Data This optional parameter may be used to pass additional data. The contents can have event-specific data.
+ For example, the FSP provides a EFI_STATUS_CODE_STRING_DATA instance to this parameter when sending debug messages.
+ This parameter is NULL when no additional data is provided.
+
+ @retval EFI_SUCCESS The event was handled successfully.
+ @retval EFI_INVALID_PARAMETER Input parameters are invalid.
+ @retval EFI_DEVICE_ERROR The event handler failed.
+*/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_EVENT_HANDLER) (
+ IN EFI_STATUS_CODE_TYPE Type,
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN UINT32 Instance,
+ IN OPTIONAL EFI_GUID *CallerId,
+ IN OPTIONAL EFI_STATUS_CODE_DATA *Data
+ );
+
+/*
+ Handler for FSP-T debug log messages, provided by the bootloader.
+
+ @param[in] DebugMessage A pointer to the debug message to be written to the log.
+ @param[in] MessageLength Number of bytes to written to the debug log.
+
+ @retval UINT32 The return value indicates the number of bytes actually written to
+ the debug log. If the return value is less than MessageLength,
+ an error occurred.
+*/
+typedef
+UINT32
+(EFIAPI *FSP_DEBUG_HANDLER) (
+ IN CHAR8* DebugMessage,
+ IN UINT32 MessageLength
+ );
+
+#pragma pack(1)
+///
+/// FSP_UPD_HEADER Configuration.
+///
+typedef struct {
+ ///
+ /// UPD Region Signature. This signature will be
+ /// "XXXXXX_T" for FSP-T
+ /// "XXXXXX_M" for FSP-M
+ /// "XXXXXX_S" for FSP-S
+ /// Where XXXXXX is an unique signature
+ ///
+ UINT64 Signature;
+ ///
+ /// Revision of the Data structure.
+ /// For FSP spec 2.0/2.1 value is 1.
+ /// For FSP spec 2.2 value is 2.
+ ///
+ UINT8 Revision;
+ UINT8 Reserved[23];
+} FSP_UPD_HEADER;
+
+///
+/// FSPT_ARCH_UPD Configuration.
+///
+typedef struct {
+ ///
+ /// Revision Revision of the structure is 1 for this version of the specification.
+ ///
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ ///
+ /// Length Length of the structure in bytes. The current value for this field is 32.
+ ///
+ UINT32 Length;
+ ///
+ /// FspDebugHandler Optional debug handler for the bootloader to receive debug messages
+ /// occurring during FSP execution.
+ ///
+ FSP_DEBUG_HANDLER FspDebugHandler;
+ UINT8 Reserved1[20];
+} FSPT_ARCH_UPD;
+
+///
+/// FSPM_ARCH_UPD Configuration.
+///
+typedef struct {
+ ///
+ /// Revision of the structure. For FSP v2.0 value is 1.
+ ///
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ ///
+ /// Pointer to the non-volatile storage (NVS) data buffer.
+ /// If it is NULL it indicates the NVS data is not available.
+ ///
+ VOID *NvsBufferPtr;
+ ///
+ /// Pointer to the temporary stack base address to be
+ /// consumed inside FspMemoryInit() API.
+ ///
+ VOID *StackBase;
+ ///
+ /// Temporary stack size to be consumed inside
+ /// FspMemoryInit() API.
+ ///
+ UINT32 StackSize;
+ ///
+ /// Size of memory to be reserved by FSP below "top
+ /// of low usable memory" for bootloader usage.
+ ///
+ UINT32 BootLoaderTolumSize;
+ ///
+ /// Current boot mode.
+ ///
+ UINT32 BootMode;
+ ///
+ /// Optional event handler for the bootloader to be informed of events occurring during FSP execution.
+ /// This value is only valid if Revision is >= 2.
+ ///
+ FSP_EVENT_HANDLER *FspEventHandler;
+ UINT8 Reserved1[4];
+} FSPM_ARCH_UPD;
+
+typedef struct {
+ ///
+ /// Revision Revision of the structure is 1 for this version of the specification.
+ ///
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ ///
+ /// Length Length of the structure in bytes. The current value for this field is 32.
+ ///
+ UINT32 Length;
+ ///
+ /// FspEventHandler Optional event handler for the bootloader to be informed of events
+ /// occurring during FSP execution.
+ ///
+ FSP_EVENT_HANDLER FspEventHandler;
+ ///
+ /// A FSP binary may optionally implement multi-phase silicon initialization,
+ /// This is only supported if the FspMultiPhaseSiInitEntryOffset field in FSP_INFO_HEADER
+ /// is non-zero.
+ /// To enable multi-phase silicon initialization, the bootloader must set
+ /// EnableMultiPhaseSiliconInit to a non-zero value.
+ ///
+ UINT8 EnableMultiPhaseSiliconInit;
+ UINT8 Reserved1[19];
+} FSPS_ARCH_UPD;
+
+///
+/// FSPT_UPD_COMMON Configuration.
+///
+typedef struct {
+ ///
+ /// FSP_UPD_HEADER Configuration.
+ ///
+ FSP_UPD_HEADER FspUpdHeader;
+} FSPT_UPD_COMMON;
+
+///
+/// FSPT_UPD_COMMON Configuration for FSP spec. 2.2 and above.
+///
+typedef struct {
+ ///
+ /// FSP_UPD_HEADER Configuration.
+ ///
+ FSP_UPD_HEADER FspUpdHeader;
+
+ ///
+ /// FSPT_ARCH_UPD Configuration.
+ ///
+ FSPT_ARCH_UPD FsptArchUpd;
+} FSPT_UPD_COMMON_FSP22;
+
+///
+/// FSPM_UPD_COMMON Configuration.
+///
+typedef struct {
+ ///
+ /// FSP_UPD_HEADER Configuration.
+ ///
+ FSP_UPD_HEADER FspUpdHeader;
+ ///
+ /// FSPM_ARCH_UPD Configuration.
+ ///
+ FSPM_ARCH_UPD FspmArchUpd;
+} FSPM_UPD_COMMON;
+
+///
+/// FSPS_UPD_COMMON Configuration.
+///
+typedef struct {
+ ///
+ /// FSP_UPD_HEADER Configuration.
+ ///
+ FSP_UPD_HEADER FspUpdHeader;
+} FSPS_UPD_COMMON;
+
+///
+/// FSPS_UPD_COMMON Configuration for FSP spec. 2.2 and above.
+///
+typedef struct {
+ ///
+ /// FSP_UPD_HEADER Configuration.
+ ///
+ FSP_UPD_HEADER FspUpdHeader;
+
+ ///
+ /// FSPS_ARCH_UPD Configuration.
+ ///
+ FSPS_ARCH_UPD FspsArchUpd;
+} FSPS_UPD_COMMON_FSP22;
+
+///
+/// Enumeration of FSP_INIT_PHASE for NOTIFY_PHASE.
+///
+typedef enum {
+ ///
+ /// This stage is notified when the bootloader completes the
+ /// PCI enumeration and the resource allocation for the
+ /// PCI devices is complete.
+ ///
+ EnumInitPhaseAfterPciEnumeration = 0x20,
+ ///
+ /// This stage is notified just before the bootloader hand-off
+ /// to the OS loader.
+ ///
+ EnumInitPhaseReadyToBoot = 0x40,
+ ///
+ /// This stage is notified just before the firmware/Preboot
+ /// environment transfers management of all system resources
+ /// to the OS or next level execution environment.
+ ///
+ EnumInitPhaseEndOfFirmware = 0xF0
+} FSP_INIT_PHASE;
+
+///
+/// Definition of NOTIFY_PHASE_PARAMS.
+///
+typedef struct {
+ ///
+ /// Notification phase used for NotifyPhase API
+ ///
+ FSP_INIT_PHASE Phase;
+} NOTIFY_PHASE_PARAMS;
+
+///
+/// Action definition for FspMultiPhaseSiInit API
+///
+typedef enum {
+ EnumMultiPhaseGetNumberOfPhases = 0x0,
+ EnumMultiPhaseExecutePhase = 0x1
+} FSP_MULTI_PHASE_ACTION;
+
+///
+/// Data structure returned by FSP when bootloader calling
+/// FspMultiPhaseSiInit API with action 0 (EnumMultiPhaseGetNumberOfPhases)
+///
+typedef struct {
+ UINT32 NumberOfPhases;
+ UINT32 PhasesExecuted;
+} FSP_MULTI_PHASE_GET_NUMBER_OF_PHASES_PARAMS;
+
+///
+/// FspMultiPhaseSiInit function parameter.
+///
+/// For action 0 (EnumMultiPhaseGetNumberOfPhases):
+/// - PhaseIndex must be 0.
+/// - MultiPhaseParamPtr should point to an instance of FSP_MULTI_PHASE_GET_NUMBER_OF_PHASES_PARAMS.
+///
+/// For action 1 (EnumMultiPhaseExecutePhase):
+/// - PhaseIndex will be the phase that will be executed by FSP.
+/// - MultiPhaseParamPtr shall be NULL.
+///
+typedef struct {
+ IN FSP_MULTI_PHASE_ACTION MultiPhaseAction;
+ IN UINT32 PhaseIndex;
+ IN OUT VOID *MultiPhaseParamPtr;
+} FSP_MULTI_PHASE_PARAMS;
+
+#pragma pack()
+
+/**
+ This FSP API is called soon after coming out of reset and before memory and stack is
+ available. This FSP API will load the microcode update, enable code caching for the
+ region specified by the boot loader and also setup a temporary stack to be used until
+ main memory is initialized.
+
+ A hardcoded stack can be set up with the following values, and the "esp" register
+ initialized to point to this hardcoded stack.
+ 1. The return address where the FSP will return control after setting up a temporary
+ stack.
+ 2. A pointer to the input parameter structure
+
+ However, since the stack is in ROM and not writeable, this FSP API cannot be called
+ using the "call" instruction, but needs to be jumped to.
+
+ @param[in] FsptUpdDataPtr Pointer to the FSPT_UPD data structure.
+
+ @retval EFI_SUCCESS Temporary RAM was initialized successfully.
+ @retval EFI_INVALID_PARAMETER Input parameters are invalid.
+ @retval EFI_UNSUPPORTED The FSP calling conditions were not met.
+ @retval EFI_DEVICE_ERROR Temp RAM initialization failed.
+
+ If this function is successful, the FSP initializes the ECX and EDX registers to point to
+ a temporary but writeable memory range available to the boot loader and returns with
+ FSP_SUCCESS in register EAX. Register ECX points to the start of this temporary
+ memory range and EDX points to the end of the range. Boot loader is free to use the
+ whole range described. Typically the boot loader can reload the ESP register to point
+ to the end of this returned range so that it can be used as a standard stack.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_TEMP_RAM_INIT) (
+ IN VOID *FsptUpdDataPtr
+ );
+
+/**
+ This FSP API is used to notify the FSP about the different phases in the boot process.
+ This allows the FSP to take appropriate actions as needed during different initialization
+ phases. The phases will be platform dependent and will be documented with the FSP
+ release. The current FSP supports two notify phases:
+ Post PCI enumeration
+ Ready To Boot
+
+ @param[in] NotifyPhaseParamPtr Address pointer to the NOTIFY_PHASE_PRAMS
+
+ @retval EFI_SUCCESS The notification was handled successfully.
+ @retval EFI_UNSUPPORTED The notification was not called in the proper order.
+ @retval EFI_INVALID_PARAMETER The notification code is invalid.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_NOTIFY_PHASE) (
+ IN NOTIFY_PHASE_PARAMS *NotifyPhaseParamPtr
+ );
+
+/**
+ This FSP API is called after TempRamInit and initializes the memory.
+ This FSP API accepts a pointer to a data structure that will be platform dependent
+ and defined for each FSP binary. This will be documented in Integration guide with
+ each FSP release.
+ After FspMemInit completes its execution, it passes the pointer to the HobList and
+ returns to the boot loader from where it was called. BootLoader is responsible to
+ migrate its stack and data to Memory.
+ FspMemoryInit, TempRamExit and FspSiliconInit APIs provide an alternate method to
+ complete the silicon initialization and provides bootloader an opportunity to get
+ control after system memory is available and before the temporary RAM is torn down.
+
+ @param[in] FspmUpdDataPtr Pointer to the FSPM_UPD data structure.
+ @param[out] HobListPtr Pointer to receive the address of the HOB list.
+
+ @retval EFI_SUCCESS FSP execution environment was initialized successfully.
+ @retval EFI_INVALID_PARAMETER Input parameters are invalid.
+ @retval EFI_UNSUPPORTED The FSP calling conditions were not met.
+ @retval EFI_DEVICE_ERROR FSP initialization failed.
+ @retval EFI_OUT_OF_RESOURCES Stack range requested by FSP is not met.
+ @retval FSP_STATUS_RESET_REQUIREDx A reset is reuired. These status codes will not be returned during S3.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_MEMORY_INIT) (
+ IN VOID *FspmUpdDataPtr,
+ OUT VOID **HobListPtr
+ );
+
+
+/**
+ This FSP API is called after FspMemoryInit API. This FSP API tears down the temporary
+ memory setup by TempRamInit API. This FSP API accepts a pointer to a data structure
+ that will be platform dependent and defined for each FSP binary. This will be
+ documented in Integration Guide.
+ FspMemoryInit, TempRamExit and FspSiliconInit APIs provide an alternate method to
+ complete the silicon initialization and provides bootloader an opportunity to get
+ control after system memory is available and before the temporary RAM is torn down.
+
+ @param[in] TempRamExitParamPtr Pointer to the Temp Ram Exit parameters structure.
+ This structure is normally defined in the Integration Guide.
+ And if it is not defined in the Integration Guide, pass NULL.
+
+ @retval EFI_SUCCESS FSP execution environment was initialized successfully.
+ @retval EFI_INVALID_PARAMETER Input parameters are invalid.
+ @retval EFI_UNSUPPORTED The FSP calling conditions were not met.
+ @retval EFI_DEVICE_ERROR FSP initialization failed.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_TEMP_RAM_EXIT) (
+ IN VOID *TempRamExitParamPtr
+ );
+
+
+/**
+ This FSP API is called after TempRamExit API.
+ FspMemoryInit, TempRamExit and FspSiliconInit APIs provide an alternate method to complete the
+ silicon initialization.
+
+ @param[in] FspsUpdDataPtr Pointer to the FSPS_UPD data structure.
+ If NULL, FSP will use the default parameters.
+
+ @retval EFI_SUCCESS FSP execution environment was initialized successfully.
+ @retval EFI_INVALID_PARAMETER Input parameters are invalid.
+ @retval EFI_UNSUPPORTED The FSP calling conditions were not met.
+ @retval EFI_DEVICE_ERROR FSP initialization failed.
+ @retval FSP_STATUS_RESET_REQUIREDx A reset is required. These status codes will not be returned during S3.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_SILICON_INIT) (
+ IN VOID *FspsUpdDataPtr
+ );
+
+/**
+ This FSP API is expected to be called after FspSiliconInit but before FspNotifyPhase.
+ This FSP API provides multi-phase silicon initialization; which brings greater modularity
+ beyond the existing FspSiliconInit() API. Increased modularity is achieved by adding an
+ extra API to FSP-S. This allows the bootloader to add board specific initialization steps
+ throughout the SiliconInit flow as needed.
+
+ @param[in,out] FSP_MULTI_PHASE_PARAMS For action - EnumMultiPhaseGetNumberOfPhases:
+ FSP_MULTI_PHASE_PARAMS->MultiPhaseParamPtr will contain
+ how many phases supported by FSP.
+ For action - EnumMultiPhaseExecutePhase:
+ FSP_MULTI_PHASE_PARAMS->MultiPhaseParamPtr shall be NULL.
+ @retval EFI_SUCCESS FSP execution environment was initialized successfully.
+ @retval EFI_INVALID_PARAMETER Input parameters are invalid.
+ @retval EFI_UNSUPPORTED The FSP calling conditions were not met.
+ @retval EFI_DEVICE_ERROR FSP initialization failed.
+ @retval FSP_STATUS_RESET_REQUIREDx A reset is required. These status codes will not be returned during S3.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_MULTI_PHASE_SI_INIT) (
+ IN FSP_MULTI_PHASE_PARAMS *MultiPhaseSiInitParamPtr
+);
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspGlobalData.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspGlobalData.h
new file mode 100644
index 00000000..2ff4c0ea
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspGlobalData.h
@@ -0,0 +1,78 @@
+/** @file
+
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_GLOBAL_DATA_H_
+#define _FSP_GLOBAL_DATA_H_
+
+#include <FspEas.h>
+
+#define FSP_IN_API_MODE 0
+#define FSP_IN_DISPATCH_MODE 1
+
+#pragma pack(1)
+
+typedef enum {
+ TempRamInitApiIndex,
+ FspInitApiIndex,
+ NotifyPhaseApiIndex,
+ FspMemoryInitApiIndex,
+ TempRamExitApiIndex,
+ FspSiliconInitApiIndex,
+ FspMultiPhaseSiInitApiIndex,
+ FspApiIndexMax
+} FSP_API_INDEX;
+
+typedef struct {
+ VOID *DataPtr;
+ UINT32 MicrocodeRegionBase;
+ UINT32 MicrocodeRegionSize;
+ UINT32 CodeRegionBase;
+ UINT32 CodeRegionSize;
+} FSP_PLAT_DATA;
+
+#define FSP_GLOBAL_DATA_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'D')
+#define FSP_PERFORMANCE_DATA_SIGNATURE SIGNATURE_32 ('P', 'E', 'R', 'F')
+#define FSP_PERFORMANCE_DATA_TIMER_MASK 0xFFFFFFFFFFFFFF
+
+typedef struct {
+ UINT32 Signature;
+ UINT8 Version;
+ UINT8 Reserved1[3];
+ UINT32 CoreStack;
+ UINT32 StatusCode;
+ UINT32 Reserved2[8];
+ FSP_PLAT_DATA PlatformData;
+ FSP_INFO_HEADER *FspInfoHeader;
+ VOID *UpdDataPtr;
+ VOID *TempRamInitUpdPtr;
+ VOID *MemoryInitUpdPtr;
+ VOID *SiliconInitUpdPtr;
+ UINT8 ApiIdx;
+ ///
+ /// 0: FSP in API mode; 1: FSP in DISPATCH mode
+ ///
+ UINT8 FspMode;
+ UINT8 OnSeparateStack;
+ UINT8 Reserved3;
+ UINT32 NumberOfPhases;
+ UINT32 PhasesExecuted;
+ ///
+ /// To store function parameters pointer
+ /// so it can be retrieved after stack switched.
+ ///
+ VOID *FunctionParameterPtr;
+ UINT8 Reserved4[16];
+ UINT32 PerfSig;
+ UINT16 PerfLen;
+ UINT16 Reserved5;
+ UINT32 PerfIdx;
+ UINT64 PerfData[32];
+} FSP_GLOBAL_DATA;
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspMeasurePointId.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspMeasurePointId.h
new file mode 100644
index 00000000..2092543f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspMeasurePointId.h
@@ -0,0 +1,56 @@
+/** @file
+
+ Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_MEASURE_POINT_ID_H_
+#define _FSP_MEASURE_POINT_ID_H_
+
+//
+// 0xD0 - 0xEF are reserved for FSP common measure point
+//
+#define FSP_PERF_ID_MRC_INIT_ENTRY 0xD0
+#define FSP_PERF_ID_MRC_INIT_EXIT (FSP_PERF_ID_MRC_INIT_ENTRY + 1)
+
+#define FSP_PERF_ID_SYSTEM_AGENT_INIT_ENTRY 0xD8
+#define FSP_PERF_ID_SYSTEM_AGENT_INIT_EXIT (FSP_PERF_ID_SYSTEM_AGENT_INIT_ENTRY + 1)
+
+#define FSP_PERF_ID_PCH_INIT_ENTRY 0xDA
+#define FSP_PERF_ID_PCH_INIT_EXIT (FSP_PERF_ID_PCH_INIT_ENTRY + 1)
+
+#define FSP_PERF_ID_CPU_INIT_ENTRY 0xE0
+#define FSP_PERF_ID_CPU_INIT_EXIT (FSP_PERF_ID_CPU_INIT_ENTRY + 1)
+
+#define FSP_PERF_ID_GFX_INIT_ENTRY 0xE8
+#define FSP_PERF_ID_GFX_INIT_EXIT (FSP_PERF_ID_GFX_INIT_ENTRY + 1)
+
+#define FSP_PERF_ID_ME_INIT_ENTRY 0xEA
+#define FSP_PERF_ID_ME_INIT_EXIT (FSP_PERF_ID_ME_INIT_ENTRY + 1)
+
+//
+// 0xF0 - 0xFF are reserved for FSP API
+//
+#define FSP_PERF_ID_API_TEMP_RAM_INIT_ENTRY 0xF0
+#define FSP_PERF_ID_API_TEMP_RAM_INIT_EXIT (FSP_PERF_ID_API_TEMP_RAM_INIT_ENTRY + 1)
+
+#define FSP_PERF_ID_API_FSP_MEMORY_INIT_ENTRY 0xF2
+#define FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT (FSP_PERF_ID_API_FSP_MEMORY_INIT_ENTRY + 1)
+
+#define FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY 0xF4
+#define FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY + 1)
+
+#define FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY 0xF6
+#define FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY + 1)
+
+#define FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY 0xF8
+#define FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + 1)
+
+#define FSP_PERF_ID_API_NOTIFY_READY_TO_BOOT_ENTRY 0xFA
+#define FSP_PERF_ID_API_NOTIFY_READY_TO_BOOT_EXIT (FSP_PERF_ID_API_NOTIFY_READY_TO_BOOT_ENTRY + 1)
+
+#define FSP_PERF_ID_API_NOTIFY_END_OF_FIRMWARE_ENTRY 0xFC
+#define FSP_PERF_ID_API_NOTIFY_END_OF_FIRMWARE_EXIT (FSP_PERF_ID_API_NOTIFY_END_OF_FIRMWARE_ENTRY + 1)
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspStatusCode.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspStatusCode.h
new file mode 100644
index 00000000..1c0954c5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspStatusCode.h
@@ -0,0 +1,40 @@
+/** @file
+ Intel FSP status code definition
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_STATUS_CODE_H_
+#define _FSP_STATUS_CODE_H_
+
+//
+// FSP API - 4 BITS
+//
+#define FSP_STATUS_CODE_TEMP_RAM_INIT 0xF000
+#define FSP_STATUS_CODE_MEMORY_INIT 0xD000
+#define FSP_STATUS_CODE_TEMP_RAM_EXIT 0xB000
+#define FSP_STATUS_CODE_SILICON_INIT 0x9000
+#define FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION 0x6000
+#define FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION 0x4000
+#define FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION 0x2000
+
+//
+// MODULE - 4 BITS
+//
+#define FSP_STATUS_CODE_GFX_PEIM 0x0700
+#define FSP_STATUS_CODE_COMMON_CODE 0x0800
+#define FSP_STATUS_CODE_SILICON_COMMON_CODE 0x0900
+#define FSP_STATUS_CODE_SYSTEM_AGENT 0x0A00
+#define FSP_STATUS_CODE_PCH 0x0B00
+#define FSP_STATUS_CODE_CPU 0x0C00
+#define FSP_STATUS_CODE_MRC 0x0D00
+#define FSP_STATUS_CODE_ME_BIOS 0x0E00
+//
+// Individual Codes - 1 BYTE
+//
+#define FSP_STATUS_CODE_API_ENTRY 0x0000
+#define FSP_STATUS_CODE_API_EXIT 0x007F
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h
new file mode 100644
index 00000000..24e20125
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h
@@ -0,0 +1,204 @@
+/** @file
+ Intel FSP Header File definition from Intel Firmware Support Package External
+ Architecture Specification v2.0 and above.
+
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __FSP_HEADER_FILE_H__
+#define __FSP_HEADER_FILE_H__
+
+#define FSP_HEADER_REVISION_3 3
+
+#define FSPE_HEADER_REVISION_1 1
+#define FSPP_HEADER_REVISION_1 1
+
+///
+/// Fixed FSP header offset in the FSP image
+///
+#define FSP_INFO_HEADER_OFF 0x94
+
+#define OFFSET_IN_FSP_INFO_HEADER(x) (UINT32)&((FSP_INFO_HEADER *)(UINTN)0)->x
+
+#define FSP_INFO_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'H')
+
+#pragma pack(1)
+
+///
+/// FSP Information Header as described in FSP v2.0 Spec section 5.1.1.
+///
+typedef struct {
+ ///
+ /// Byte 0x00: Signature ('FSPH') for the FSP Information Header.
+ ///
+ UINT32 Signature;
+ ///
+ /// Byte 0x04: Length of the FSP Information Header.
+ ///
+ UINT32 HeaderLength;
+ ///
+ /// Byte 0x08: Reserved.
+ ///
+ UINT8 Reserved1[2];
+ ///
+ /// Byte 0x0A: Indicates compliance with a revision of this specification in the BCD format.
+ ///
+ UINT8 SpecVersion;
+ ///
+ /// Byte 0x0B: Revision of the FSP Information Header.
+ ///
+ UINT8 HeaderRevision;
+ ///
+ /// Byte 0x0C: Revision of the FSP binary.
+ ///
+ UINT32 ImageRevision;
+ ///
+ /// Byte 0x10: Signature string that will help match the FSP Binary to a supported HW configuration.
+ ///
+ CHAR8 ImageId[8];
+ ///
+ /// Byte 0x18: Size of the entire FSP binary.
+ ///
+ UINT32 ImageSize;
+ ///
+ /// Byte 0x1C: FSP binary preferred base address.
+ ///
+ UINT32 ImageBase;
+ ///
+ /// Byte 0x20: Attribute for the FSP binary.
+ ///
+ UINT16 ImageAttribute;
+ ///
+ /// Byte 0x22: Attributes of the FSP Component.
+ ///
+ UINT16 ComponentAttribute;
+ ///
+ /// Byte 0x24: Offset of the FSP configuration region.
+ ///
+ UINT32 CfgRegionOffset;
+ ///
+ /// Byte 0x28: Size of the FSP configuration region.
+ ///
+ UINT32 CfgRegionSize;
+ ///
+ /// Byte 0x2C: Reserved2.
+ ///
+ UINT32 Reserved2;
+ ///
+ /// Byte 0x30: The offset for the API to setup a temporary stack till the memory is initialized.
+ ///
+ UINT32 TempRamInitEntryOffset;
+ ///
+ /// Byte 0x34: Reserved3.
+ ///
+ UINT32 Reserved3;
+ ///
+ /// Byte 0x38: The offset for the API to inform the FSP about the different stages in the boot process.
+ ///
+ UINT32 NotifyPhaseEntryOffset;
+ ///
+ /// Byte 0x3C: The offset for the API to initialize the memory.
+ ///
+ UINT32 FspMemoryInitEntryOffset;
+ ///
+ /// Byte 0x40: The offset for the API to tear down temporary RAM.
+ ///
+ UINT32 TempRamExitEntryOffset;
+ ///
+ /// Byte 0x44: The offset for the API to initialize the CPU and chipset.
+ ///
+ UINT32 FspSiliconInitEntryOffset;
+ ///
+ /// Byte 0x48: Offset for the API for the optional Multi-Phase processor and chipset initialization.
+ /// This value is only valid if FSP HeaderRevision is >= 5.
+ /// If the value is set to 0x00000000, then this API is not available in this component.
+ ///
+ UINT32 FspMultiPhaseSiInitEntryOffset;
+} FSP_INFO_HEADER;
+
+///
+/// Signature of the FSP Extended Header
+///
+#define FSP_INFO_EXTENDED_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'E')
+
+///
+/// FSP Information Extended Header as described in FSP v2.0 Spec section 5.1.2.
+///
+typedef struct {
+ ///
+ /// Byte 0x00: Signature ('FSPE') for the FSP Extended Information Header.
+ ///
+ UINT32 Signature;
+ ///
+ /// Byte 0x04: Length of the table in bytes, including all additional FSP producer defined data.
+ ///
+ UINT32 Length;
+ ///
+ /// Byte 0x08: FSP producer defined revision of the table.
+ ///
+ UINT8 Revision;
+ ///
+ /// Byte 0x09: Reserved for future use.
+ ///
+ UINT8 Reserved;
+ ///
+ /// Byte 0x0A: FSP producer identification string
+ ///
+ CHAR8 FspProducerId[6];
+ ///
+ /// Byte 0x10: FSP producer implementation revision number. Larger numbers are assumed to be newer revisions.
+ ///
+ UINT32 FspProducerRevision;
+ ///
+ /// Byte 0x14: Size of the FSP producer defined data (n) in bytes.
+ ///
+ UINT32 FspProducerDataSize;
+ ///
+ /// Byte 0x18: FSP producer defined data of size (n) defined by FspProducerDataSize.
+ ///
+} FSP_INFO_EXTENDED_HEADER;
+
+//
+// A generic table search algorithm for additional tables can be implemented with a
+// signature search algorithm until a terminator signature 'FSPP' is found.
+//
+#define FSP_FSPP_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'P')
+#define FSP_PATCH_TABLE_SIGNATURE FSP_FSPP_SIGNATURE
+
+///
+/// FSP Patch Table as described in FSP v2.0 Spec section 5.1.5.
+///
+typedef struct {
+ ///
+ /// Byte 0x00: FSP Patch Table Signature "FSPP".
+ ///
+ UINT32 Signature;
+ ///
+ /// Byte 0x04: Size including the PatchData.
+ ///
+ UINT16 HeaderLength;
+ ///
+ /// Byte 0x06: Revision is set to 0x01.
+ ///
+ UINT8 HeaderRevision;
+ ///
+ /// Byte 0x07: Reserved for future use.
+ ///
+ UINT8 Reserved;
+ ///
+ /// Byte 0x08: Number of entries to Patch.
+ ///
+ UINT32 PatchEntryNum;
+ ///
+ /// Byte 0x0C: Patch Data.
+ ///
+//UINT32 PatchData[];
+} FSP_PATCH_TABLE;
+
+#pragma pack()
+
+extern EFI_GUID gFspHeaderFileGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Guid/GuidHobFspEas.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Guid/GuidHobFspEas.h
new file mode 100644
index 00000000..631eef36
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Guid/GuidHobFspEas.h
@@ -0,0 +1,17 @@
+/** @file
+ Intel FSP Hob Guid definition from Intel Firmware Support Package External
+ Architecture Specification v2.0.
+
+ Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __GUID_HOB_FSP_EAS_GUID__
+#define __GUID_HOB_FSP_EAS_GUID__
+
+extern EFI_GUID gFspBootLoaderTolumHobGuid;
+extern EFI_GUID gFspReservedMemoryResourceHobGuid;
+extern EFI_GUID gFspNonVolatileStorageHobGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/CacheAsRamLib.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/CacheAsRamLib.h
new file mode 100644
index 00000000..c2a4e678
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/CacheAsRamLib.h
@@ -0,0 +1,24 @@
+/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _CACHE_AS_RAM_LIB_H_
+#define _CACHE_AS_RAM_LIB_H_
+
+/**
+ This function disable CAR.
+
+ @param[in] DisableCar TRUE means use INVD, FALSE means use WBINVD
+
+**/
+VOID
+EFIAPI
+DisableCacheAsRam (
+ IN BOOLEAN DisableCar
+ );
+
+#endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/CacheLib.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/CacheLib.h
new file mode 100644
index 00000000..7548b7e1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/CacheLib.h
@@ -0,0 +1,56 @@
+/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _CACHE_LIB_H_
+#define _CACHE_LIB_H_
+
+//
+// EFI_MEMORY_CACHE_TYPE
+//
+typedef INT32 EFI_MEMORY_CACHE_TYPE;
+
+#define EFI_CACHE_UNCACHEABLE 0
+#define EFI_CACHE_WRITECOMBINING 1
+#define EFI_CACHE_WRITETHROUGH 4
+#define EFI_CACHE_WRITEPROTECTED 5
+#define EFI_CACHE_WRITEBACK 6
+
+/**
+ Reset all the MTRRs to a known state.
+
+ @retval EFI_SUCCESS All MTRRs have been reset successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+ResetCacheAttributes (
+ VOID
+ );
+
+/**
+ Given the memory range and cache type, programs the MTRRs.
+
+ @param[in] MemoryAddress Base Address of Memory to program MTRR.
+ @param[in] MemoryLength Length of Memory to program MTRR.
+ @param[in] MemoryCacheType Cache Type.
+
+ @retval EFI_SUCCESS Mtrr are set successfully.
+ @retval EFI_LOAD_ERROR No empty MTRRs to use.
+ @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+ @retval others An error occurs when setting MTTR.
+
+**/
+EFI_STATUS
+EFIAPI
+SetCacheAttributes (
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ );
+
+#endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/DebugDeviceLib.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/DebugDeviceLib.h
new file mode 100644
index 00000000..f8611909
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/DebugDeviceLib.h
@@ -0,0 +1,23 @@
+/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __DEBUG_DEVICE_LIB_H__
+#define __DEBUG_DEVICE_LIB_H__
+
+/**
+ Returns the debug print device enable state.
+
+ @return Debug print device enable state.
+
+**/
+UINT8
+EFIAPI
+GetDebugPrintDeviceEnable (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspCommonLib.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspCommonLib.h
new file mode 100644
index 00000000..dfc87ae6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspCommonLib.h
@@ -0,0 +1,308 @@
+/** @file
+
+ Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_COMMON_LIB_H_
+#define _FSP_COMMON_LIB_H_
+
+#include <FspGlobalData.h>
+#include <FspMeasurePointId.h>
+
+/**
+ This function sets the FSP global data pointer.
+
+ @param[in] FspData Fsp global data pointer.
+
+**/
+VOID
+EFIAPI
+SetFspGlobalDataPointer (
+ IN FSP_GLOBAL_DATA *FspData
+ );
+
+/**
+ This function gets the FSP global data pointer.
+
+**/
+FSP_GLOBAL_DATA *
+EFIAPI
+GetFspGlobalDataPointer (
+ VOID
+ );
+
+/**
+ This function gets back the FSP API first parameter passed by the bootloader.
+
+ @retval ApiParameter FSP API first parameter passed by the bootloader.
+**/
+UINT32
+EFIAPI
+GetFspApiParameter (
+ VOID
+ );
+
+/**
+ This function gets back the FSP API second parameter passed by the bootloader.
+
+ @retval ApiParameter FSP API second parameter passed by the bootloader.
+**/
+UINT32
+EFIAPI
+GetFspApiParameter2 (
+ VOID
+ );
+
+/**
+ This function returns the FSP entry stack pointer from address of the first API parameter.
+
+ @retval FSP entry stack pointer.
+**/
+VOID*
+EFIAPI
+GetFspEntryStack (
+ VOID
+ );
+
+/**
+ This function sets the FSP API parameter in the stack.
+
+ @param[in] Value New parameter value.
+
+**/
+VOID
+EFIAPI
+SetFspApiParameter (
+ IN UINT32 Value
+ );
+
+/**
+ This function set the API status code returned to the BootLoader.
+
+ @param[in] ReturnStatus Status code to return.
+
+**/
+VOID
+EFIAPI
+SetFspApiReturnStatus (
+ IN UINT32 ReturnStatus
+ );
+
+/**
+ This function sets the context switching stack to a new stack frame.
+
+ @param[in] NewStackTop New core stack to be set.
+
+**/
+VOID
+EFIAPI
+SetFspCoreStackPointer (
+ IN VOID *NewStackTop
+ );
+
+/**
+ This function sets the platform specific data pointer.
+
+ @param[in] PlatformData Fsp platform specific data pointer.
+
+**/
+VOID
+EFIAPI
+SetFspPlatformDataPointer (
+ IN VOID *PlatformData
+ );
+
+/**
+ This function gets the platform specific data pointer.
+
+ @param[in] PlatformData Fsp platform specific data pointer.
+
+**/
+VOID *
+EFIAPI
+GetFspPlatformDataPointer (
+ VOID
+ );
+
+/**
+ This function sets the UPD data pointer.
+
+ @param[in] UpdDataPtr UPD data pointer.
+**/
+VOID
+EFIAPI
+SetFspUpdDataPointer (
+ IN VOID *UpdDataPtr
+ );
+
+/**
+ This function gets the UPD data pointer.
+
+ @return UpdDataPtr UPD data pointer.
+**/
+VOID *
+EFIAPI
+GetFspUpdDataPointer (
+ VOID
+ );
+
+/**
+ This function sets the memory init UPD data pointer.
+
+ @param[in] MemoryInitUpdPtr memory init UPD data pointer.
+**/
+VOID
+EFIAPI
+SetFspMemoryInitUpdDataPointer (
+ IN VOID *MemoryInitUpdPtr
+ );
+
+/**
+ This function gets the memory init UPD data pointer.
+
+ @return memory init UPD data pointer.
+**/
+VOID *
+EFIAPI
+GetFspMemoryInitUpdDataPointer (
+ VOID
+ );
+
+/**
+ This function sets the silicon init UPD data pointer.
+
+ @param[in] SiliconInitUpdPtr silicon init UPD data pointer.
+**/
+VOID
+EFIAPI
+SetFspSiliconInitUpdDataPointer (
+ IN VOID *SiliconInitUpdPtr
+ );
+
+/**
+ This function gets the silicon init UPD data pointer.
+
+ @return silicon init UPD data pointer.
+**/
+VOID *
+EFIAPI
+GetFspSiliconInitUpdDataPointer (
+ VOID
+ );
+
+/**
+ Set FSP measurement point timestamp.
+
+ @param[in] Id Measurement point ID.
+
+ @return performance timestamp.
+**/
+UINT64
+EFIAPI
+SetFspMeasurePoint (
+ IN UINT8 Id
+ );
+
+/**
+ This function gets the FSP info header pointer.
+
+ @retval FspInfoHeader FSP info header pointer
+**/
+FSP_INFO_HEADER *
+EFIAPI
+GetFspInfoHeader (
+ VOID
+ );
+
+/**
+ This function sets the FSP info header pointer.
+
+ @param[in] FspInfoHeader FSP info header pointer
+**/
+VOID
+EFIAPI
+SetFspInfoHeader (
+ FSP_INFO_HEADER *FspInfoHeader
+ );
+
+/**
+ This function gets the FSP info header pointer from the API context.
+
+ @retval FspInfoHeader FSP info header pointer
+**/
+FSP_INFO_HEADER *
+EFIAPI
+GetFspInfoHeaderFromApiContext (
+ VOID
+ );
+
+/**
+ This function gets the CfgRegion data pointer.
+
+ @return CfgRegion data pointer.
+**/
+VOID *
+EFIAPI
+GetFspCfgRegionDataPointer (
+ VOID
+ );
+
+/**
+ This function gets FSP API calling mode.
+
+ @retval API calling mode
+**/
+UINT8
+EFIAPI
+GetFspApiCallingIndex (
+ VOID
+ );
+
+/**
+ This function sets FSP API calling mode.
+
+ @param[in] Index API calling index
+**/
+VOID
+EFIAPI
+SetFspApiCallingIndex (
+ UINT8 Index
+ );
+
+/**
+ This function gets FSP Phase StatusCode.
+
+ @retval StatusCode
+**/
+UINT32
+EFIAPI
+GetPhaseStatusCode (
+ VOID
+ );
+
+
+/**
+ This function sets FSP Phase StatusCode.
+
+ @param[in] Mode Phase StatusCode
+**/
+VOID
+EFIAPI
+SetPhaseStatusCode (
+ UINT32 StatusCode
+ );
+
+/**
+ This function updates the return status of the FSP API with requested reset type and returns to Boot Loader.
+
+ @param[in] FspResetType Reset type that needs to returned as API return status
+
+**/
+VOID
+EFIAPI
+FspApiReturnStatusReset (
+ IN UINT32 FspResetType
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspPlatformLib.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspPlatformLib.h
new file mode 100644
index 00000000..680416b4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspPlatformLib.h
@@ -0,0 +1,125 @@
+/** @file
+
+ Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_PLATFORM_LIB_H_
+#define _FSP_PLATFORM_LIB_H_
+
+/**
+ Get system memory resource descriptor by owner.
+
+ @param[in] OwnerGuid resource owner guid
+**/
+EFI_HOB_RESOURCE_DESCRIPTOR *
+EFIAPI
+FspGetResourceDescriptorByOwner (
+ IN EFI_GUID *OwnerGuid
+ );
+
+/**
+ Get system memory from HOB.
+
+ @param[in,out] LowMemoryLength less than 4G memory length
+ @param[in,out] HighMemoryLength greater than 4G memory length
+**/
+VOID
+EFIAPI
+FspGetSystemMemorySize (
+ IN OUT UINT64 *LowMemoryLength,
+ IN OUT UINT64 *HighMemoryLength
+ );
+
+
+/**
+ Set a new stack frame for the continuation function.
+
+**/
+VOID
+EFIAPI
+FspSetNewStackFrame (
+ VOID
+ );
+
+/**
+ This function transfer control back to BootLoader after FspSiliconInit.
+
+**/
+VOID
+EFIAPI
+FspSiliconInitDone (
+ VOID
+ );
+
+/**
+ This function returns control to BootLoader after MemoryInitApi.
+
+ @param[in,out] HobListPtr The address of HobList pointer.
+**/
+VOID
+EFIAPI
+FspMemoryInitDone (
+ IN OUT VOID **HobListPtr
+ );
+
+/**
+ This function returns control to BootLoader after TempRamExitApi.
+
+**/
+VOID
+EFIAPI
+FspTempRamExitDone (
+ VOID
+ );
+
+/**
+ This function handle NotifyPhase API call from the BootLoader.
+ It gives control back to the BootLoader after it is handled. If the
+ Notification code is a ReadyToBoot event, this function will return
+ and FSP continues the remaining execution until it reaches the DxeIpl.
+
+**/
+VOID
+EFIAPI
+FspWaitForNotify (
+ VOID
+ );
+
+/**
+ This function transfer control back to BootLoader after FspSiliconInit.
+
+ @param[in] Status return status for the FspSiliconInit.
+**/
+VOID
+EFIAPI
+FspSiliconInitDone2 (
+ IN EFI_STATUS Status
+ );
+
+/**
+ This function returns control to BootLoader after MemoryInitApi.
+
+ @param[in] Status return status for the MemoryInitApi.
+ @param[in,out] HobListPtr The address of HobList pointer.
+**/
+VOID
+EFIAPI
+FspMemoryInitDone2 (
+ IN EFI_STATUS Status,
+ IN OUT VOID **HobListPtr
+ );
+
+/**
+ This function returns control to BootLoader after TempRamExitApi.
+
+ @param[in] Status return status for the TempRamExitApi.
+**/
+VOID
+EFIAPI
+FspTempRamExitDone2 (
+ IN EFI_STATUS Status
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspSecPlatformLib.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspSecPlatformLib.h
new file mode 100644
index 00000000..d6ecbd47
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspSecPlatformLib.h
@@ -0,0 +1,96 @@
+/** @file
+
+ Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_SEC_PLATFORM_LIB_H_
+#define _FSP_SEC_PLATFORM_LIB_H_
+
+/**
+ This function performs platform level initialization.
+
+ This function must be in ASM file, because stack is not established yet.
+ This function is optional. If a library instance does not provide this function, the default empty one will be used.
+
+ The callee should not use XMM6/XMM7.
+ The return address is saved in MM7.
+
+ @retval in saved in EAX - 0 means platform initialization success.
+ other means platform initialization fail.
+**/
+UINT32
+EFIAPI
+SecPlatformInit (
+ VOID
+ );
+
+/**
+ This function loads Microcode.
+
+ This function must be in ASM file, because stack is not established yet.
+ This function is optional. If a library instance does not provide this function, the default one will be used.
+
+ The callee should not use XMM6/XMM7.
+ The return address is saved in MM7.
+
+ @param[in] FsptUpdDataPtr Address pointer to the FSPT_UPD data structure. It is saved in ESP.
+
+ @retval in saved in EAX - 0 means Microcode is loaded successfully.
+ other means Microcode is not loaded successfully.
+**/
+UINT32
+EFIAPI
+LoadMicrocode (
+ IN VOID *FsptUpdDataPtr
+ );
+
+/**
+ This function initializes the CAR.
+
+ This function must be in ASM file, because stack is not established yet.
+
+ The callee should not use XMM6/XMM7.
+ The return address is saved in MM7.
+
+ @param[in] FsptUpdDataPtr Address pointer to the FSPT_UPD data structure. It is saved in ESP.
+
+ @retval in saved in EAX - 0 means CAR initialization success.
+ other means CAR initialization fail.
+**/
+UINT32
+EFIAPI
+SecCarInit (
+ IN VOID *FsptUpdDataPtr
+ );
+
+/**
+ This function check the signature of UPD.
+
+ @param[in] ApiIdx Internal index of the FSP API.
+ @param[in] ApiParam Parameter of the FSP API.
+
+**/
+EFI_STATUS
+EFIAPI
+FspUpdSignatureCheck (
+ IN UINT32 ApiIdx,
+ IN VOID *ApiParam
+ );
+
+/**
+ This function handles FspMultiPhaseSiInitApi.
+
+ @param[in] ApiIdx Internal index of the FSP API.
+ @param[in] ApiParam Parameter of the FSP API.
+
+**/
+EFI_STATUS
+EFIAPI
+FspMultiPhaseSiInitApiHandler (
+ IN UINT32 ApiIdx,
+ IN VOID *ApiParam
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspSwitchStackLib.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspSwitchStackLib.h
new file mode 100644
index 00000000..259a5760
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Library/FspSwitchStackLib.h
@@ -0,0 +1,55 @@
+/** @file
+
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_SWITCH_STACK_LIB_H_
+#define _FSP_SWITCH_STACK_LIB_H_
+
+/**
+
+ This function will switch the current stack to the previous saved stack.
+ Before calling the previous stack has to be set in FSP_GLOBAL_DATA.CoreStack.
+ EIP
+ FLAGS 16 bit FLAGS 16 bit
+ EDI
+ ESI
+ EBP
+ ESP
+ EBX
+ EDX
+ ECX
+ EAX
+ DWORD IDT base1
+ StackPointer: DWORD IDT base2
+
+ @return ReturnKey After switching to the saved stack,
+ this value will be saved in eax before returning.
+
+
+**/
+UINT32
+EFIAPI
+Pei2LoaderSwitchStack (
+ VOID
+ );
+
+/**
+
+ This function is equivalent to Pei2LoaderSwitchStack () but just indicates
+ the stack after switched is FSP stack.
+
+ @return ReturnKey After switching to the saved stack,
+ this value will be saved in eax before returning.
+
+
+**/
+UINT32
+EFIAPI
+Loader2PeiSwitchStack (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Ppi/FspmArchConfigPpi.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Ppi/FspmArchConfigPpi.h
new file mode 100644
index 00000000..e3c62a94
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Ppi/FspmArchConfigPpi.h
@@ -0,0 +1,47 @@
+/** @file
+ Header file for FSP-M Arch Config PPI for Dispatch mode
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSPM_ARCH_CONFIG_PPI_H_
+#define _FSPM_ARCH_CONFIG_PPI_H_
+
+#define FSPM_ARCH_CONFIG_PPI_REVISION 0x1
+
+///
+/// Global ID for the FSPM_ARCH_CONFIG_PPI.
+///
+#define FSPM_ARCH_CONFIG_GUID \
+ { \
+ 0x824d5a3a, 0xaf92, 0x4c0c, { 0x9f, 0x19, 0x19, 0x52, 0x6d, 0xca, 0x4a, 0xbb } \
+ }
+
+///
+/// This PPI provides FSP-M Arch Config PPI.
+///
+typedef struct {
+ ///
+ /// Revision of the structure
+ ///
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ ///
+ /// Pointer to the non-volatile storage (NVS) data buffer.
+ /// If it is NULL it indicates the NVS data is not available.
+ ///
+ VOID *NvsBufferPtr;
+ ///
+ /// Size of memory to be reserved by FSP below "top
+ /// of low usable memory" for bootloader usage.
+ ///
+ UINT32 BootLoaderTolumSize;
+ UINT8 Reserved1[4];
+} FSPM_ARCH_CONFIG_PPI;
+
+extern EFI_GUID gFspmArchConfigPpiGuid;
+
+#endif // _FSPM_ARCH_CONFIG_PPI_H_
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Ppi/TempRamExitPpi.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Ppi/TempRamExitPpi.h
new file mode 100644
index 00000000..ed3a1c19
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/Ppi/TempRamExitPpi.h
@@ -0,0 +1,52 @@
+/** @file
+ This file defines the Silicon Temp Ram Exit PPI which implements the
+ required programming steps for disabling temporary memory.
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_TEMP_RAM_EXIT_PPI_H_
+#define _FSP_TEMP_RAM_EXIT_PPI_H_
+
+///
+/// Global ID for the FSP_TEMP_RAM_EXIT_PPI.
+///
+#define FSP_TEMP_RAM_EXIT_GUID \
+ { \
+ 0xbc1cfbdb, 0x7e50, 0x42be, { 0xb4, 0x87, 0x22, 0xe0, 0xa9, 0x0c, 0xb0, 0x52 } \
+ }
+
+//
+// Forward declaration for the FSP_TEMP_RAM_EXIT_PPI.
+//
+typedef struct _FSP_TEMP_RAM_EXIT_PPI FSP_TEMP_RAM_EXIT_PPI;
+
+/**
+ Silicon function for disabling temporary memory.
+ @param[in] TempRamExitParamPtr - Pointer to the TempRamExit parameters structure.
+ This structure is normally defined in the Integration
+ Guide. If it is not defined in the Integration Guide,
+ pass NULL.
+ @retval EFI_SUCCESS - FSP execution environment was initialized successfully.
+ @retval EFI_INVALID_PARAMETER - Input parameters are invalid.
+ @retval EFI_UNSUPPORTED - The FSP calling conditions were not met.
+ @retval EFI_DEVICE_ERROR - Temporary memory exit.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FSP_TEMP_RAM_EXIT) (
+ IN VOID *TempRamExitParamPtr
+ );
+
+///
+/// This PPI provides function to disable temporary memory.
+///
+struct _FSP_TEMP_RAM_EXIT_PPI {
+ FSP_TEMP_RAM_EXIT TempRamExit;
+};
+
+extern EFI_GUID gFspTempRamExitPpiGuid;
+
+#endif // _FSP_TEMP_RAM_EXIT_PPI_H_
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dec b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dec
new file mode 100644
index 00000000..d49f8227
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dec
@@ -0,0 +1,109 @@
+## @file
+# Provides driver and definitions to build 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 = IntelFsp2Pkg
+ PACKAGE_GUID = A8C53B5E-D556-4F3E-874D-0D6FA2CDC7BF
+ PACKAGE_VERSION = 0.1
+
+[Includes]
+ Include
+
+[LibraryClasses]
+ ## @libraryclass Provides cache-as-ram support.
+ CacheAsRamLib|Include/Library/CacheAsRamLib.h
+
+ ## @libraryclass Provides cache setting on MTRR.
+ CacheLib|Include/Library/CacheLib.h
+
+ ## @libraryclass Provides debug device abstraction.
+ DebugDeviceLib|Include/Library/DebugDeviceLib.h
+
+ ## @libraryclass Provides FSP related services.
+ FspCommonLib|Include/Library/FspCommonLib.h
+
+ ## @libraryclass Provides FSP platform related actions.
+ FspPlatformLib|Include/Library/FspPlatformLib.h
+
+ ## @libraryclass Provides FSP switch stack function.
+ FspSwitchStackLib|Include/Library/FspSwitchStackLib.h
+
+ ## @libraryclass Provides FSP platform sec related actions.
+ FspSecPlatformLib|Include/Library/FspSecPlatformLib.h
+
+[Ppis]
+ #
+ # PPI to indicate FSP is ready to enter notify phase
+ # This provides flexibility for any late initialization that must be done right before entering notify phase.
+ #
+ gFspReadyForNotifyPhasePpiGuid = { 0xcd167c1e, 0x6e0b, 0x42b3, {0x82, 0xf6, 0xe3, 0xe9, 0x06, 0x19, 0x98, 0x10}}
+
+ #
+ # PPI as dependency on some modules which only required for API mode
+ #
+ gFspInApiModePpiGuid = { 0xa1eeab87, 0xc859, 0x479d, {0x89, 0xb5, 0x14, 0x61, 0xf4, 0x06, 0x1a, 0x3e}}
+
+ #
+ # PPI for Architectural configuration data for FSP-M
+ #
+ gFspmArchConfigPpiGuid = { 0x824d5a3a, 0xaf92, 0x4c0c, {0x9f, 0x19, 0x19, 0x52, 0x6d, 0xca, 0x4a, 0xbb}}
+
+ #
+ # PPI to tear down the temporary memory set up by TempRamInit ().
+ #
+ gFspTempRamExitPpiGuid = { 0xbc1cfbdb, 0x7e50, 0x42be, {0xb4, 0x87, 0x22, 0xe0, 0xa9, 0x0c, 0xb0, 0x52}}
+
+[Guids]
+ #
+ # GUID defined in package
+ #
+ gIntelFsp2PkgTokenSpaceGuid = { 0xed6e0531, 0xf715, 0x4a3d, { 0x9b, 0x12, 0xc1, 0xca, 0x5e, 0xf6, 0x98, 0xa2 } }
+
+ # Guid define in FSP EAS
+ gFspHeaderFileGuid = { 0x912740BE, 0x2284, 0x4734, { 0xB9, 0x71, 0x84, 0xB0, 0x27, 0x35, 0x3F, 0x0C } }
+ gFspReservedMemoryResourceHobGuid = { 0x69a79759, 0x1373, 0x4367, { 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e } }
+ gFspNonVolatileStorageHobGuid = { 0x721acf02, 0x4d77, 0x4c2a, { 0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0 } }
+ gFspBootLoaderTolumHobGuid = { 0x73ff4f56, 0xaa8e, 0x4451, { 0xb3, 0x16, 0x36, 0x35, 0x36, 0x67, 0xad, 0x44 } } # FSP EAS v1.1
+
+ gFspPerformanceDataGuid = { 0x56ed21b6, 0xba23, 0x429e, { 0x89, 0x32, 0x37, 0x6d, 0x8e, 0x18, 0x2e, 0xe3 } }
+ gFspEventEndOfFirmwareGuid = { 0xbd44f629, 0xeae7, 0x4198, { 0x87, 0xf1, 0x39, 0xfa, 0xb0, 0xfd, 0x71, 0x7e } }
+
+[PcdsFixedAtBuild]
+ gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress |0xFED00108|UINT32|0x00000001
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase |0xFEF00000|UINT32|0x10001001
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize | 0x2000|UINT32|0x10001002
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize | 0x1000|UINT32|0x10001003
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedBufferSize | 0x100|UINT32|0x10001004
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPerfEntry | 32|UINT32|0x00002001
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPatchEntry | 6|UINT32|0x00002002
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspAreaBaseAddress |0xFFF80000|UINT32|0x10000001
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspAreaSize |0x00040000|UINT32|0x10000002
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspBootFirmwareVolumeBase|0xFFF80000|UINT32|0x10000003
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspHeaderSpecVersion | 0x20| UINT8|0x00000002
+
+ #
+ # x % of FSP temporary memory will be used for heap
+ # (100 - x) % of FSP temporary memory will be used for stack
+ # 0 means FSP will share the stack with boot loader and FSP temporary memory is heap
+ # Note: This mode assumes boot loader stack is large enough for FSP to use.
+ #
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspHeapSizePercentage | 50| UINT8|0x10000004
+ #
+ # Maximal Interrupt supported in IDT table.
+ #
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxInterruptSupported | 34| UINT8|0x10000005
+ #
+ # Allows FSP-M to reserve a section of Temporary RAM for implementation specific use.
+ # Reduces the amount of memory available for the PeiCore heap.
+ #
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspPrivateTemporaryRamSize |0x00000000|UINT32|0x10000006
+
+[PcdsFixedAtBuild,PcdsDynamic,PcdsDynamicEx]
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedMemoryLength |0x00100000|UINT32|0x46530000
+ gIntelFsp2PkgTokenSpaceGuid.PcdBootLoaderEntry |0xFFFFFFE4|UINT32|0x46530100
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dsc b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dsc
new file mode 100644
index 00000000..74af2bfb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dsc
@@ -0,0 +1,80 @@
+## @file
+# Provides driver and definitions to build fsp.
+#
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = IntelFsp2Pkg
+ PLATFORM_GUID = 55CA3D18-831B-469A-A1C3-7AE719EB6A97
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/IntelFsp2Pkg
+ SUPPORTED_ARCHITECTURES = IA32
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses]
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ DebugDeviceLib|IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf
+
+ # FSP override
+ DebugLib|IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf
+
+ # FSP specific lib
+ CacheAsRamLib|IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf
+ CacheLib|IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf
+ FspCommonLib|IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
+ FspPlatformLib|IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
+ FspSwitchStackLib|IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
+ FspSecPlatformLib|IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf
+
+[LibraryClasses.common.PEIM]
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+
+[Components]
+ IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf
+ IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf
+ IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
+ IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf
+ IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
+ IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
+ IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf
+ IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf
+
+ IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
+ IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
+ IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf
+ IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
+ IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf
+
+[PcdsFixedAtBuild.common]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80080046
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+
+[BuildOptions]
+ *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf
new file mode 100644
index 00000000..2bfebf17
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf
@@ -0,0 +1,26 @@
+## @file
+# NULL instance of Base cache as RAM.
+#
+# Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseCacheAsRamLibNull
+ FILE_GUID = 630AEB10-2106-4234-9DB3-836A3663F50D
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CacheAsRamLib
+
+[Sources.common]
+ DisableCacheAsRamNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c
new file mode 100644
index 00000000..5c8aa938
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c
@@ -0,0 +1,35 @@
+/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/CacheAsRamLib.h>
+
+/**
+ This function disable CAR.
+
+ @param[in] DisableCar TRUE means use INVD, FALSE means use WBINVD
+
+**/
+VOID
+EFIAPI
+DisableCacheAsRam (
+ IN BOOLEAN DisableCar
+ )
+{
+ //
+ // Disable CAR
+ //
+
+ if (DisableCar) {
+ AsmInvd ();
+ } else {
+ AsmWbinvd();
+ }
+
+ return ;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf
new file mode 100644
index 00000000..d0bcab04
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf
@@ -0,0 +1,29 @@
+## @file
+# Instance of BaseCache.
+#
+# Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseCacheLib
+ FILE_GUID = 8EF3A653-DA8B-4FFA-BB85-FF47406DB9F0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CacheLib
+
+[Sources.IA32]
+ CacheLib.c
+ CacheLibInternal.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ CacheAsRamLib
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c
new file mode 100644
index 00000000..503715f8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c
@@ -0,0 +1,697 @@
+/** @file
+
+ Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/CacheLib.h>
+#include <Library/CacheAsRamLib.h>
+#include "CacheLibInternal.h"
+
+/**
+ Search the memory cache type for specific memory from MTRR.
+
+ @param[in] MemoryAddress the address of target memory
+ @param[in] MemoryLength the length of target memory
+ @param[in] ValidMtrrAddressMask the MTRR address mask
+ @param[out] UsedMsrNum the used MSR number
+ @param[out] UsedMemoryCacheType the cache type for the target memory
+
+ @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned
+ @retval EFI_NOT_FOUND The memory is not found in MTRR
+
+**/
+EFI_STATUS
+SearchForExactMtrr (
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN UINT64 ValidMtrrAddressMask,
+ OUT UINT32 *UsedMsrNum,
+ OUT EFI_MEMORY_CACHE_TYPE *MemoryCacheType
+ );
+
+/**
+ Check if CacheType match current default setting.
+
+ @param[in] MemoryCacheType input cache type to be checked.
+
+ @retval TRUE MemoryCacheType is default MTRR setting.
+ @retval FALSE MemoryCacheType is NOT default MTRR setting.
+**/
+BOOLEAN
+IsDefaultType (
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ );
+
+/**
+ Return MTRR alignment requirement for base address and size.
+
+ @param[in] BaseAddress Base address.
+ @param[in] Size Size.
+
+ @retval Zero Aligned.
+ @retval Non-Zero Not aligned.
+
+**/
+UINT32
+CheckMtrrAlignment (
+ IN UINT64 BaseAddress,
+ IN UINT64 Size
+ );
+
+typedef struct {
+ UINT32 Msr;
+ UINT32 BaseAddress;
+ UINT32 Length;
+} EFI_FIXED_MTRR;
+
+EFI_FIXED_MTRR mFixedMtrrTable[] = {
+ { EFI_MSR_IA32_MTRR_FIX64K_00000, 0, 0x10000},
+ { EFI_MSR_IA32_MTRR_FIX16K_80000, 0x80000, 0x4000},
+ { EFI_MSR_IA32_MTRR_FIX16K_A0000, 0xA0000, 0x4000},
+ { EFI_MSR_IA32_MTRR_FIX4K_C0000, 0xC0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_C8000, 0xC8000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_D0000, 0xD0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_D8000, 0xD8000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_E0000, 0xE0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_E8000, 0xE8000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_F0000, 0xF0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_F8000, 0xF8000, 0x1000}
+};
+
+/**
+ Given the input, check if the number of MTRR is lesser.
+ if positive or subtractive.
+
+ @param[in] Input Length of Memory to program MTRR.
+
+ @retval Zero do positive.
+ @retval Non-Zero do subtractive.
+
+**/
+INT8
+CheckDirection (
+ IN UINT64 Input
+ )
+{
+ return 0;
+}
+
+/**
+ Disable cache and its mtrr.
+
+ @param[out] OldMtrr To return the Old MTRR value
+
+**/
+VOID
+EfiDisableCacheMtrr (
+ OUT UINT64 *OldMtrr
+ )
+{
+ UINT64 TempQword;
+
+ //
+ // Disable Cache MTRR
+ //
+ *OldMtrr = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
+ TempQword = (*OldMtrr) & ~B_EFI_MSR_GLOBAL_MTRR_ENABLE & ~B_EFI_MSR_FIXED_MTRR_ENABLE;
+ AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);
+ AsmDisableCache ();
+}
+
+/**
+ Recover cache MTRR.
+
+ @param[in] EnableMtrr Whether to enable the MTRR
+ @param[in] OldMtrr The saved old MTRR value to restore when not to enable the MTRR
+
+**/
+VOID
+EfiRecoverCacheMtrr (
+ IN BOOLEAN EnableMtrr,
+ IN UINT64 OldMtrr
+ )
+{
+ UINT64 TempQword;
+
+ //
+ // Enable Cache MTRR
+ //
+ if (EnableMtrr) {
+ TempQword = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
+ TempQword |= (UINT64)(B_EFI_MSR_GLOBAL_MTRR_ENABLE | B_EFI_MSR_FIXED_MTRR_ENABLE);
+ } else {
+ TempQword = OldMtrr;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);
+
+ AsmEnableCache ();
+}
+
+/**
+ Programming MTRR according to Memory address, length, and type.
+
+ @param[in] MtrrNumber the variable MTRR index number
+ @param[in] MemoryAddress the address of target memory
+ @param[in] MemoryLength the length of target memory
+ @param[in] MemoryCacheType the cache type of target memory
+ @param[in] ValidMtrrAddressMask the MTRR address mask
+
+**/
+VOID
+EfiProgramMtrr (
+ IN UINTN MtrrNumber,
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,
+ IN UINT64 ValidMtrrAddressMask
+ )
+{
+ UINT64 TempQword;
+ UINT64 OldMtrr;
+
+ if (MemoryLength == 0) {
+ return;
+ }
+
+ EfiDisableCacheMtrr (&OldMtrr);
+
+ //
+ // MTRR Physical Base
+ //
+ TempQword = (MemoryAddress & ValidMtrrAddressMask) | MemoryCacheType;
+ AsmWriteMsr64 (MtrrNumber, TempQword);
+
+ //
+ // MTRR Physical Mask
+ //
+ TempQword = ~(MemoryLength - 1);
+ AsmWriteMsr64 (MtrrNumber + 1, (TempQword & ValidMtrrAddressMask) | B_EFI_MSR_CACHE_MTRR_VALID);
+
+ EfiRecoverCacheMtrr (TRUE, OldMtrr);
+}
+
+/**
+ Calculate the maximum value which is a power of 2, but less the MemoryLength.
+
+ @param[in] MemoryAddress Memory address.
+ @param[in] MemoryLength The number to pass in.
+
+ @return The maximum value which is align to power of 2 and less the MemoryLength
+
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryAddress,
+ IN UINT64 MemoryLength
+ )
+{
+ UINT64 Result;
+
+ if (MemoryLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Compute initial power of 2 size to return
+ //
+ Result = GetPowerOfTwo64(MemoryLength);
+
+ //
+ // Special case base of 0 as all ranges are valid
+ //
+ if (MemoryAddress == 0) {
+ return Result;
+ }
+
+ //
+ // Loop till a value that can be mapped to this base address is found
+ //
+ while (CheckMtrrAlignment (MemoryAddress, Result) != 0) {
+ //
+ // Need to try the next smaller power of 2
+ //
+ Result = RShiftU64 (Result, 1);
+ }
+
+ return Result;
+}
+
+/**
+ Return MTRR alignment requirement for base address and size.
+
+ @param[in] BaseAddress Base address.
+ @param[in] Size Size.
+
+ @retval Zero Aligned.
+ @retval Non-Zero Not aligned.
+
+**/
+UINT32
+CheckMtrrAlignment (
+ IN UINT64 BaseAddress,
+ IN UINT64 Size
+ )
+{
+ UINT32 ShiftedBase;
+ UINT32 ShiftedSize;
+
+ //
+ // Shift base and size right 12 bits to allow for larger memory sizes. The
+ // MTRRs do not use the first 12 bits so this is safe for now. Only supports
+ // up to 52 bits of physical address space.
+ //
+ ShiftedBase = (UINT32) RShiftU64 (BaseAddress, 12);
+ ShiftedSize = (UINT32) RShiftU64 (Size, 12);
+
+ //
+ // Return the results to the caller of the MOD
+ //
+ return ShiftedBase % ShiftedSize;
+}
+
+/**
+ Programs fixed MTRRs registers.
+
+ @param[in] MemoryCacheType The memory type to set.
+ @param[in] Base The base address of memory range.
+ @param[in] Length The length of memory range.
+
+ @retval RETURN_SUCCESS The cache type was updated successfully
+ @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
+ for the fixed MTRRs.
+
+**/
+EFI_STATUS
+ProgramFixedMtrr (
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,
+ IN UINT64 *Base,
+ IN UINT64 *Len
+ )
+{
+ UINT32 MsrNum;
+ UINT32 ByteShift;
+ UINT64 TempQword;
+ UINT64 OrMask;
+ UINT64 ClearMask;
+
+ TempQword = 0;
+ OrMask = 0;
+ ClearMask = 0;
+
+ for (MsrNum = 0; MsrNum < V_EFI_FIXED_MTRR_NUMBER; MsrNum++) {
+ if ((*Base >= mFixedMtrrTable[MsrNum].BaseAddress) &&
+ (*Base < (mFixedMtrrTable[MsrNum].BaseAddress + 8 * mFixedMtrrTable[MsrNum].Length))) {
+ break;
+ }
+ }
+ if (MsrNum == V_EFI_FIXED_MTRR_NUMBER ) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // We found the fixed MTRR to be programmed
+ //
+ for (ByteShift=0; ByteShift < 8; ByteShift++) {
+ if ( *Base == (mFixedMtrrTable[MsrNum].BaseAddress + ByteShift * mFixedMtrrTable[MsrNum].Length)) {
+ break;
+ }
+ }
+ if (ByteShift == 8 ) {
+ return EFI_DEVICE_ERROR;
+ }
+ for (; ((ByteShift<8) && (*Len >= mFixedMtrrTable[MsrNum].Length));ByteShift++) {
+ OrMask |= LShiftU64((UINT64) MemoryCacheType, (UINT32) (ByteShift* 8));
+ ClearMask |= LShiftU64((UINT64) 0xFF, (UINT32) (ByteShift * 8));
+ *Len -= mFixedMtrrTable[MsrNum].Length;
+ *Base += mFixedMtrrTable[MsrNum].Length;
+ }
+ TempQword = (AsmReadMsr64 (mFixedMtrrTable[MsrNum].Msr) & (~ClearMask)) | OrMask;
+ AsmWriteMsr64 (mFixedMtrrTable[MsrNum].Msr, TempQword);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if there is a valid variable MTRR that overlaps the given range.
+
+ @param[in] Start Base Address of the range to check.
+ @param[in] End End address of the range to check.
+
+ @retval TRUE Mtrr overlap.
+ @retval FALSE Mtrr not overlap.
+**/
+BOOLEAN
+CheckMtrrOverlap (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End
+ )
+{
+ return FALSE;
+}
+
+/**
+ Given the memory range and cache type, programs the MTRRs.
+
+ @param[in] MemoryAddress Base Address of Memory to program MTRR.
+ @param[in] MemoryLength Length of Memory to program MTRR.
+ @param[in] MemoryCacheType Cache Type.
+
+ @retval EFI_SUCCESS Mtrr are set successfully.
+ @retval EFI_LOAD_ERROR No empty MTRRs to use.
+ @retval EFI_INVALID_PARAMETER The input parameter is not valid.
+ @retval others An error occurs when setting MTTR.
+
+**/
+EFI_STATUS
+EFIAPI
+SetCacheAttributes (
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ )
+{
+ EFI_STATUS Status;
+ UINT32 MsrNum, MsrNumEnd;
+ UINT64 TempQword;
+ UINT32 LastVariableMtrrForBios;
+ UINT64 OldMtrr;
+ UINT32 UsedMsrNum;
+ EFI_MEMORY_CACHE_TYPE UsedMemoryCacheType;
+ UINT64 ValidMtrrAddressMask;
+ UINT32 Cpuid_RegEax;
+
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &Cpuid_RegEax, NULL, NULL, NULL);
+ if (Cpuid_RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Cpuid_RegEax, NULL, NULL, NULL);
+ ValidMtrrAddressMask = (LShiftU64((UINT64) 1, (Cpuid_RegEax & 0xFF)) - 1) & (~(UINT64)0x0FFF);
+ } else {
+ ValidMtrrAddressMask = (LShiftU64((UINT64) 1, 36) - 1) & (~(UINT64)0x0FFF);
+ }
+
+ //
+ // Check for invalid parameter
+ //
+ if ((MemoryAddress & ~ValidMtrrAddressMask) != 0 || (MemoryLength & ~ValidMtrrAddressMask) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MemoryLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (MemoryCacheType) {
+ case EFI_CACHE_UNCACHEABLE:
+ case EFI_CACHE_WRITECOMBINING:
+ case EFI_CACHE_WRITETHROUGH:
+ case EFI_CACHE_WRITEPROTECTED:
+ case EFI_CACHE_WRITEBACK:
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if Fixed MTRR
+ //
+ if ((MemoryAddress + MemoryLength) <= (1 << 20)) {
+ Status = EFI_SUCCESS;
+ EfiDisableCacheMtrr (&OldMtrr);
+ while ((MemoryLength > 0) && (Status == EFI_SUCCESS)) {
+ Status = ProgramFixedMtrr (MemoryCacheType, &MemoryAddress, &MemoryLength);
+ }
+ EfiRecoverCacheMtrr (TRUE, OldMtrr);
+ return Status;
+ }
+
+ //
+ // Search if the range attribute has been set before
+ //
+ Status = SearchForExactMtrr(
+ MemoryAddress,
+ MemoryLength,
+ ValidMtrrAddressMask,
+ &UsedMsrNum,
+ &UsedMemoryCacheType
+ );
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Compare if it has the same type as current setting
+ //
+ if (UsedMemoryCacheType == MemoryCacheType) {
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Different type
+ //
+
+ //
+ // Check if the set type is the same as Default Type
+ //
+ if (IsDefaultType(MemoryCacheType)) {
+ //
+ // Clear the MTRR
+ //
+ AsmWriteMsr64(UsedMsrNum, 0);
+ AsmWriteMsr64(UsedMsrNum + 1, 0);
+
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Modify the MTRR type
+ //
+ EfiProgramMtrr(UsedMsrNum,
+ MemoryAddress,
+ MemoryLength,
+ MemoryCacheType,
+ ValidMtrrAddressMask
+ );
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+#if 0
+ //
+ // @bug - Need to create memory map so that when checking for overlap we
+ // can determine if an overlap exists based on all caching requests.
+ //
+ // Don't waste a variable MTRR if the caching attrib is same as default in MTRR_DEF_TYPE
+ //
+ if (MemoryCacheType == (AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE)) {
+ if (!CheckMtrrOverlap (MemoryAddress, MemoryAddress+MemoryLength-1)) {
+ return EFI_SUCCESS;
+ }
+ }
+#endif
+
+ //
+ // Find first unused MTRR
+ //
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) {
+ if ((AsmReadMsr64(MsrNum+1) & B_EFI_MSR_CACHE_MTRR_VALID) == 0 ) {
+ break;
+ }
+ }
+
+ //
+ // Reserve 1 MTRR pair for OS.
+ //
+ LastVariableMtrrForBios = MsrNumEnd - 1 - (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2);
+ if (MsrNum > LastVariableMtrrForBios) {
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // Special case for 1 MB base address
+ //
+ if (MemoryAddress == BASE_1MB) {
+ MemoryAddress = 0;
+ }
+
+ //
+ // Program MTRRs
+ //
+ TempQword = MemoryLength;
+
+ if (TempQword == Power2MaxMemory(MemoryAddress, TempQword)) {
+ EfiProgramMtrr(MsrNum,
+ MemoryAddress,
+ MemoryLength,
+ MemoryCacheType,
+ ValidMtrrAddressMask
+ );
+
+ } else {
+ //
+ // Fill in MTRRs with values. Direction can not be checked for this method
+ // as we are using WB as the default cache type and only setting areas to UC.
+ //
+ do {
+ //
+ // Do boundary check so we don't go past last MTRR register
+ // for BIOS use. Leave one MTRR pair for OS use.
+ //
+ if (MsrNum > LastVariableMtrrForBios) {
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // Set next power of 2 region
+ //
+ MemoryLength = Power2MaxMemory(MemoryAddress, TempQword);
+ EfiProgramMtrr(MsrNum,
+ MemoryAddress,
+ MemoryLength,
+ MemoryCacheType,
+ ValidMtrrAddressMask
+ );
+ MemoryAddress += MemoryLength;
+ TempQword -= MemoryLength;
+ MsrNum += 2;
+ } while (TempQword != 0);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reset all the MTRRs to a known state.
+
+ @retval EFI_SUCCESS All MTRRs have been reset successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+ResetCacheAttributes (
+ VOID
+ )
+{
+ UINT32 MsrNum, MsrNumEnd;
+ UINT16 Index;
+ UINT64 OldMtrr;
+ UINT64 CacheType;
+ BOOLEAN DisableCar;
+ Index = 0;
+ DisableCar = TRUE;
+
+ //
+ // Determine default cache type
+ //
+ CacheType = EFI_CACHE_UNCACHEABLE;
+
+ //
+ // Set default cache type
+ //
+ AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, CacheType);
+
+ //
+ // Disable CAR
+ //
+ DisableCacheAsRam (DisableCar);
+
+ EfiDisableCacheMtrr (&OldMtrr);
+
+ //
+ // Reset Fixed MTRRs
+ //
+ for (Index = 0; Index < V_EFI_FIXED_MTRR_NUMBER; Index++) {
+ AsmWriteMsr64 (mFixedMtrrTable[Index].Msr, 0);
+ }
+
+ //
+ // Reset Variable MTRRs
+ //
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum++) {
+ AsmWriteMsr64 (MsrNum, 0);
+ }
+
+ //
+ // Enable Fixed and Variable MTRRs
+ //
+ EfiRecoverCacheMtrr (TRUE, OldMtrr);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search the memory cache type for specific memory from MTRR.
+
+ @param[in] MemoryAddress the address of target memory
+ @param[in] MemoryLength the length of target memory
+ @param[in] ValidMtrrAddressMask the MTRR address mask
+ @param[out] UsedMsrNum the used MSR number
+ @param[out] UsedMemoryCacheType the cache type for the target memory
+
+ @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned
+ @retval EFI_NOT_FOUND The memory is not found in MTRR
+
+**/
+EFI_STATUS
+SearchForExactMtrr (
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN UINT64 ValidMtrrAddressMask,
+ OUT UINT32 *UsedMsrNum,
+ OUT EFI_MEMORY_CACHE_TYPE *UsedMemoryCacheType
+ )
+{
+ UINT32 MsrNum, MsrNumEnd;
+ UINT64 TempQword;
+
+ if (MemoryLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) {
+ TempQword = AsmReadMsr64(MsrNum+1);
+ if ((TempQword & B_EFI_MSR_CACHE_MTRR_VALID) == 0) {
+ continue;
+ }
+
+ if ((TempQword & ValidMtrrAddressMask) != ((~(MemoryLength - 1)) & ValidMtrrAddressMask)) {
+ continue;
+ }
+
+ TempQword = AsmReadMsr64 (MsrNum);
+ if ((TempQword & ValidMtrrAddressMask) != (MemoryAddress & ValidMtrrAddressMask)) {
+ continue;
+ }
+
+ *UsedMemoryCacheType = (EFI_MEMORY_CACHE_TYPE)(TempQword & B_EFI_MSR_CACHE_MEMORY_TYPE);
+ *UsedMsrNum = MsrNum;
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Check if CacheType match current default setting.
+
+ @param[in] MemoryCacheType input cache type to be checked.
+
+ @retval TRUE MemoryCacheType is default MTRR setting.
+ @retval TRUE MemoryCacheType is NOT default MTRR setting.
+**/
+BOOLEAN
+IsDefaultType (
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ )
+{
+ if ((AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE) != MemoryCacheType) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/CacheLibInternal.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/CacheLibInternal.h
new file mode 100644
index 00000000..2b82476d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseCacheLib/CacheLibInternal.h
@@ -0,0 +1,53 @@
+/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _CACHE_LIB_INTERNAL_H_
+#define _CACHE_LIB_INTERNAL_H_
+
+#define EFI_MSR_CACHE_VARIABLE_MTRR_BASE 0x00000200
+#define EFI_MSR_CACHE_VARIABLE_MTRR_END 0x0000020F
+#define V_EFI_FIXED_MTRR_NUMBER 11
+
+#define EFI_MSR_IA32_MTRR_FIX64K_00000 0x00000250
+#define EFI_MSR_IA32_MTRR_FIX16K_80000 0x00000258
+#define EFI_MSR_IA32_MTRR_FIX16K_A0000 0x00000259
+#define EFI_MSR_IA32_MTRR_FIX4K_C0000 0x00000268
+#define EFI_MSR_IA32_MTRR_FIX4K_C8000 0x00000269
+#define EFI_MSR_IA32_MTRR_FIX4K_D0000 0x0000026A
+#define EFI_MSR_IA32_MTRR_FIX4K_D8000 0x0000026B
+#define EFI_MSR_IA32_MTRR_FIX4K_E0000 0x0000026C
+#define EFI_MSR_IA32_MTRR_FIX4K_E8000 0x0000026D
+#define EFI_MSR_IA32_MTRR_FIX4K_F0000 0x0000026E
+#define EFI_MSR_IA32_MTRR_FIX4K_F8000 0x0000026F
+#define EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE 0x000002FF
+#define B_EFI_MSR_CACHE_MTRR_VALID BIT11
+#define B_EFI_MSR_GLOBAL_MTRR_ENABLE BIT11
+#define B_EFI_MSR_FIXED_MTRR_ENABLE BIT10
+#define B_EFI_MSR_CACHE_MEMORY_TYPE (BIT2 | BIT1 | BIT0)
+
+#define EFI_MSR_VALID_MASK 0xFFFFFFFFF
+#define EFI_CACHE_VALID_ADDRESS 0xFFFFFF000
+#define EFI_SMRR_CACHE_VALID_ADDRESS 0xFFFFF000
+#define EFI_CACHE_VALID_EXTENDED_ADDRESS 0xFFFFFFFFFF000
+
+// Leave one MTRR pairs for OS use
+#define EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS 1
+#define EFI_CACHE_LAST_VARIABLE_MTRR_FOR_BIOS (EFI_MSR_CACHE_VARIABLE_MTRR_END) - \
+ (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2)
+
+#define EFI_MSR_IA32_MTRR_CAP 0x000000FE
+#define B_EFI_MSR_IA32_MTRR_CAP_EMRR_SUPPORT BIT12
+#define B_EFI_MSR_IA32_MTRR_CAP_SMRR_SUPPORT BIT11
+#define B_EFI_MSR_IA32_MTRR_CAP_WC_SUPPORT BIT10
+#define B_EFI_MSR_IA32_MTRR_CAP_FIXED_SUPPORT BIT8
+#define B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+
+#define CPUID_VIR_PHY_ADDRESS_SIZE 0x80000008
+#define CPUID_EXTENDED_FUNCTION 0x80000000
+
+#endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf
new file mode 100644
index 00000000..26e91e9d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf
@@ -0,0 +1,29 @@
+## @file
+# Debug device library instance that retrieves the current enabling state for
+# the platform debug output device.
+#
+# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseDebugDeviceLibNull
+ FILE_GUID = 5E975522-176F-4E2D-BB25-64ADCC7792A4
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DebugDeviceLib
+
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ DebugDeviceLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c
new file mode 100644
index 00000000..76c57320
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c
@@ -0,0 +1,25 @@
+/** @file
+ Debug device library instance that retrieves the current enabling state for
+ the platform debug output device.
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+/**
+ Returns the debug print device enable state.
+
+ @return Debug print device enable state.
+
+**/
+UINT8
+EFIAPI
+GetDebugPrintDeviceEnable (
+ VOID
+ )
+{
+ return 1;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
new file mode 100644
index 00000000..9c377ba8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
@@ -0,0 +1,30 @@
+## @file
+# Instance of FspCommonLib
+# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseFspCommonLib
+ FILE_GUID = 38BE57E8-902C-485A-AB5E-D5AEC613194D
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FspCommonLib
+
+[Sources]
+ FspCommonLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ FspSwitchStackLib
+
+[Pcd]
+ gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress ## CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c
new file mode 100644
index 00000000..a0f54afe
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c
@@ -0,0 +1,545 @@
+/** @file
+
+ Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <FspGlobalData.h>
+#include <FspEas.h>
+#include <Library/FspSwitchStackLib.h>
+
+#pragma pack(1)
+
+//
+// API Parameter +0x34
+// API return address +0x30
+//
+// push FspInfoHeader +0x2C
+// pushfd +0x28
+// cli
+// pushad +0x24
+// sub esp, 8 +0x00
+// sidt fword ptr [esp]
+//
+typedef struct {
+ UINT16 IdtrLimit;
+ UINT32 IdtrBase;
+ UINT16 Reserved;
+ UINT32 Edi;
+ UINT32 Esi;
+ UINT32 Ebp;
+ UINT32 Esp;
+ UINT32 Ebx;
+ UINT32 Edx;
+ UINT32 Ecx;
+ UINT32 Eax;
+ UINT16 Flags[2];
+ UINT32 FspInfoHeader;
+ UINT32 ApiRet;
+ UINT32 ApiParam[2];
+} CONTEXT_STACK;
+
+#define CONTEXT_STACK_OFFSET(x) (UINT32)&((CONTEXT_STACK *)(UINTN)0)->x
+
+#pragma pack()
+
+/**
+ This function sets the FSP global data pointer.
+
+ @param[in] FspData FSP global data pointer.
+
+**/
+VOID
+EFIAPI
+SetFspGlobalDataPointer (
+ IN FSP_GLOBAL_DATA *FspData
+ )
+{
+ ASSERT (FspData != NULL);
+ *((volatile UINT32 *)(UINTN)PcdGet32(PcdGlobalDataPointerAddress)) = (UINT32)(UINTN)FspData;
+}
+
+/**
+ This function gets the FSP global data pointer.
+
+**/
+FSP_GLOBAL_DATA *
+EFIAPI
+GetFspGlobalDataPointer (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = *(FSP_GLOBAL_DATA **)(UINTN)PcdGet32(PcdGlobalDataPointerAddress);
+ return FspData;
+}
+
+/**
+ This function gets back the FSP API first parameter passed by the bootloader.
+
+ @retval ApiParameter FSP API first parameter passed by the bootloader.
+**/
+UINT32
+EFIAPI
+GetFspApiParameter (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam[0]));
+}
+
+/**
+ This function returns the FSP entry stack pointer from address of the first API parameter.
+
+ @retval FSP entry stack pointer.
+**/
+VOID*
+EFIAPI
+GetFspEntryStack (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return (VOID*)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam[0]));
+}
+
+/**
+ This function gets back the FSP API second parameter passed by the bootloader.
+
+ @retval ApiParameter FSP API second parameter passed by the bootloader.
+**/
+UINT32
+EFIAPI
+GetFspApiParameter2 (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam[1]));
+}
+
+/**
+ This function sets the FSP API parameter in the stack.
+
+ @param[in] Value New parameter value.
+
+**/
+VOID
+EFIAPI
+SetFspApiParameter (
+ IN UINT32 Value
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam)) = Value;
+}
+
+/**
+ This function set the API status code returned to the BootLoader.
+
+ @param[in] ReturnStatus Status code to return.
+
+**/
+VOID
+EFIAPI
+SetFspApiReturnStatus (
+ IN UINT32 ReturnStatus
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(Eax)) = ReturnStatus;
+}
+
+/**
+ This function sets the context switching stack to a new stack frame.
+
+ @param[in] NewStackTop New core stack to be set.
+
+**/
+VOID
+EFIAPI
+SetFspCoreStackPointer (
+ IN VOID *NewStackTop
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+ UINT32 *OldStack;
+ UINT32 *NewStack;
+ UINT32 StackContextLen;
+
+ FspData = GetFspGlobalDataPointer ();
+ StackContextLen = sizeof(CONTEXT_STACK) / sizeof(UINT32);
+
+ //
+ // Reserve space for the ContinuationFunc two parameters
+ //
+ OldStack = (UINT32 *)FspData->CoreStack;
+ NewStack = (UINT32 *)NewStackTop - StackContextLen - 2;
+ FspData->CoreStack = (UINT32)NewStack;
+ while (StackContextLen-- != 0) {
+ *NewStack++ = *OldStack++;
+ }
+}
+
+/**
+ This function sets the platform specific data pointer.
+
+ @param[in] PlatformData FSP platform specific data pointer.
+
+**/
+VOID
+EFIAPI
+SetFspPlatformDataPointer (
+ IN VOID *PlatformData
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ FspData->PlatformData.DataPtr = PlatformData;
+}
+
+
+/**
+ This function gets the platform specific data pointer.
+
+ @param[in] PlatformData FSP platform specific data pointer.
+
+**/
+VOID *
+EFIAPI
+GetFspPlatformDataPointer (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return FspData->PlatformData.DataPtr;
+}
+
+
+/**
+ This function sets the UPD data pointer.
+
+ @param[in] UpdDataPtr UPD data pointer.
+**/
+VOID
+EFIAPI
+SetFspUpdDataPointer (
+ IN VOID *UpdDataPtr
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ //
+ // Get the FSP Global Data Pointer
+ //
+ FspData = GetFspGlobalDataPointer ();
+
+ //
+ // Set the UPD pointer.
+ //
+ FspData->UpdDataPtr = UpdDataPtr;
+}
+
+/**
+ This function gets the UPD data pointer.
+
+ @return UpdDataPtr UPD data pointer.
+**/
+VOID *
+EFIAPI
+GetFspUpdDataPointer (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return FspData->UpdDataPtr;
+}
+
+
+/**
+ This function sets the FspMemoryInit UPD data pointer.
+
+ @param[in] MemoryInitUpdPtr FspMemoryInit UPD data pointer.
+**/
+VOID
+EFIAPI
+SetFspMemoryInitUpdDataPointer (
+ IN VOID *MemoryInitUpdPtr
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ //
+ // Get the FSP Global Data Pointer
+ //
+ FspData = GetFspGlobalDataPointer ();
+
+ //
+ // Set the FspMemoryInit UPD pointer.
+ //
+ FspData->MemoryInitUpdPtr = MemoryInitUpdPtr;
+}
+
+/**
+ This function gets the FspMemoryInit UPD data pointer.
+
+ @return FspMemoryInit UPD data pointer.
+**/
+VOID *
+EFIAPI
+GetFspMemoryInitUpdDataPointer (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return FspData->MemoryInitUpdPtr;
+}
+
+
+/**
+ This function sets the FspSiliconInit UPD data pointer.
+
+ @param[in] SiliconInitUpdPtr FspSiliconInit UPD data pointer.
+**/
+VOID
+EFIAPI
+SetFspSiliconInitUpdDataPointer (
+ IN VOID *SiliconInitUpdPtr
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ //
+ // Get the FSP Global Data Pointer
+ //
+ FspData = GetFspGlobalDataPointer ();
+
+ //
+ // Set the FspSiliconInit UPD data pointer.
+ //
+ FspData->SiliconInitUpdPtr = SiliconInitUpdPtr;
+}
+
+/**
+ This function gets the FspSiliconInit UPD data pointer.
+
+ @return FspSiliconInit UPD data pointer.
+**/
+VOID *
+EFIAPI
+GetFspSiliconInitUpdDataPointer (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return FspData->SiliconInitUpdPtr;
+}
+
+
+/**
+ Set FSP measurement point timestamp.
+
+ @param[in] Id Measurement point ID.
+
+ @return performance timestamp.
+**/
+UINT64
+EFIAPI
+SetFspMeasurePoint (
+ IN UINT8 Id
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ //
+ // Bit [55: 0] will be the timestamp
+ // Bit [63:56] will be the ID
+ //
+ FspData = GetFspGlobalDataPointer ();
+ if (FspData->PerfIdx < sizeof(FspData->PerfData) / sizeof(FspData->PerfData[0])) {
+ FspData->PerfData[FspData->PerfIdx] = AsmReadTsc ();
+ ((UINT8 *)(&FspData->PerfData[FspData->PerfIdx]))[7] = Id;
+ }
+
+ return FspData->PerfData[(FspData->PerfIdx)++];
+}
+
+/**
+ This function gets the FSP info header pointer.
+
+ @retval FspInfoHeader FSP info header pointer
+**/
+FSP_INFO_HEADER *
+EFIAPI
+GetFspInfoHeader (
+ VOID
+ )
+{
+ return GetFspGlobalDataPointer()->FspInfoHeader;
+}
+
+/**
+ This function sets the FSP info header pointer.
+
+ @param[in] FspInfoHeader FSP info header pointer
+**/
+VOID
+EFIAPI
+SetFspInfoHeader (
+ FSP_INFO_HEADER *FspInfoHeader
+ )
+{
+ GetFspGlobalDataPointer()->FspInfoHeader = FspInfoHeader;
+}
+
+/**
+ This function gets the FSP info header pointer using the API stack context.
+
+ @retval FspInfoHeader FSP info header pointer using the API stack context
+**/
+FSP_INFO_HEADER *
+EFIAPI
+GetFspInfoHeaderFromApiContext (
+ VOID
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ return (FSP_INFO_HEADER *)(*(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(FspInfoHeader)));
+}
+
+/**
+ This function gets the CfgRegion data pointer.
+
+ @return CfgRegion data pointer.
+**/
+VOID *
+EFIAPI
+GetFspCfgRegionDataPointer (
+ VOID
+ )
+{
+ FSP_INFO_HEADER *FspInfoHeader;
+
+ FspInfoHeader = GetFspInfoHeader ();
+ return (VOID *)(FspInfoHeader->ImageBase + FspInfoHeader->CfgRegionOffset);
+}
+
+/**
+ This function gets FSP API calling index.
+
+ @retval API calling index
+**/
+UINT8
+EFIAPI
+GetFspApiCallingIndex (
+ VOID
+ )
+{
+ return GetFspGlobalDataPointer()->ApiIdx;
+}
+
+/**
+ This function sets FSP API calling mode.
+
+ @param[in] Index API calling index
+**/
+VOID
+EFIAPI
+SetFspApiCallingIndex (
+ UINT8 Index
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ FspData->ApiIdx = Index;
+}
+
+/**
+ This function gets FSP Phase StatusCode.
+
+ @retval StatusCode
+**/
+UINT32
+EFIAPI
+GetPhaseStatusCode (
+ VOID
+ )
+{
+ return GetFspGlobalDataPointer()->StatusCode;
+}
+
+/**
+ This function sets FSP Phase StatusCode.
+
+ @param[in] Mode Phase StatusCode
+**/
+VOID
+EFIAPI
+SetPhaseStatusCode (
+ UINT32 StatusCode
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+
+ FspData = GetFspGlobalDataPointer ();
+ FspData->StatusCode = StatusCode;
+}
+
+/**
+ This function updates the return status of the FSP API with requested reset type and returns to Boot Loader.
+
+ @param[in] FspResetType Reset type that needs to returned as API return status
+
+**/
+VOID
+EFIAPI
+FspApiReturnStatusReset (
+ IN UINT32 FspResetType
+ )
+{
+ volatile BOOLEAN LoopUntilReset;
+
+ LoopUntilReset = TRUE;
+ DEBUG ((DEBUG_INFO, "FSP returning control to Bootloader with reset required return status %x\n",FspResetType));
+ if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {
+ ///
+ /// Below code is not an infinite loop.The control will go back to API calling function in BootLoader each time BootLoader
+ /// calls the FSP API without honoring the reset request by FSP
+ ///
+ do {
+ SetFspApiReturnStatus ((EFI_STATUS)FspResetType);
+ Pei2LoaderSwitchStack ();
+ DEBUG ((DEBUG_ERROR, "!!!ERROR: FSP has requested BootLoader for reset. But BootLoader has not honored the reset\n"));
+ DEBUG ((DEBUG_ERROR, "!!!ERROR: Please add support in BootLoader to honor the reset request from FSP\n"));
+ } while (LoopUntilReset);
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf
new file mode 100644
index 00000000..a90f01a4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf
@@ -0,0 +1,45 @@
+## @file
+# Instance of BaseFspDebugLib
+#
+# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseFspDebugLibSerialPort
+ FILE_GUID = CEA4FF9C-D7BC-4F07-96F1-03F41F2B17AE
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DebugLib
+
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources]
+ DebugLib.c
+
+[Sources.Ia32]
+ Ia32/FspDebug.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+ SerialPortLib
+ BaseMemoryLib
+ PcdLib
+ PrintLib
+ BaseLib
+ DebugDeviceLib
+ DebugPrintErrorLevelLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/DebugLib.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/DebugLib.c
new file mode 100644
index 00000000..5c34a6b8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/DebugLib.c
@@ -0,0 +1,415 @@
+/** @file
+
+ Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PrintLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/DebugDeviceLib.h>
+#include <Library/DebugPrintErrorLevelLib.h>
+
+//
+// Define the maximum debug and assert message length that this library supports
+//
+#define MAX_DEBUG_MESSAGE_LENGTH 0x100
+
+CONST CHAR8 *mHexTable = "0123456789ABCDEF";
+
+//
+// VA_LIST can not initialize to NULL for all compiler, so we use this to
+// indicate a null VA_LIST
+//
+VA_LIST mVaListNull;
+
+/**
+ Get stack frame pointer of function call.
+
+ @return StackFramePointer stack frame pointer of function call.
+**/
+UINT32 *
+EFIAPI
+GetStackFramePointer (
+ VOID
+ );
+
+
+/**
+ Prints a debug message to the debug output device if the specified error level is enabled.
+
+ If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
+ GetDebugPrintErrorLevel (), then print the message specified by Format and the
+ associated variable argument list to the debug output device.
+
+ If Format is NULL, then ASSERT().
+
+ @param ErrorLevel The error level of the debug message.
+ @param Format Format string for the debug message to print.
+ @param ... Variable argument list whose contents are accessed
+ based on the format string specified by Format.
+
+**/
+VOID
+EFIAPI
+DebugPrint (
+ IN UINTN ErrorLevel,
+ IN CONST CHAR8 *Format,
+ ...
+ )
+{
+ VA_LIST Marker;
+
+ VA_START (Marker, Format);
+ DebugVPrint (ErrorLevel, Format, Marker);
+ VA_END (Marker);
+}
+
+/**
+ Prints a debug message to the debug output device if the specified
+ error level is enabled base on Null-terminated format string and a
+ VA_LIST argument list or a BASE_LIST argument list.
+
+ If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
+ GetDebugPrintErrorLevel (), then print the message specified by Format and
+ the associated variable argument list to the debug output device.
+
+ If Format is NULL, then ASSERT().
+
+ @param ErrorLevel The error level of the debug message.
+ @param Format Format string for the debug message to print.
+ @param VaListMarker VA_LIST marker for the variable argument list.
+ @param BaseListMarker BASE_LIST marker for the variable argument list.
+
+**/
+VOID
+DebugPrintMarker (
+ IN UINTN ErrorLevel,
+ IN CONST CHAR8 *Format,
+ IN VA_LIST VaListMarker,
+ IN BASE_LIST BaseListMarker
+ )
+{
+ CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
+
+ //
+ // If Format is NULL, then ASSERT().
+ //
+ if (!GetDebugPrintDeviceEnable ()) {
+ return;
+ }
+
+ //
+ // Check driver debug mask value and global mask
+ //
+ if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
+ return;
+ }
+
+ //
+ // If Format is NULL, then ASSERT().
+ //
+ ASSERT (Format != NULL);
+
+ //
+ // Convert the DEBUG() message to an ASCII String
+ //
+ if (BaseListMarker == NULL) {
+ AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaListMarker);
+ } else {
+ AsciiBSPrint (Buffer, sizeof (Buffer), Format, BaseListMarker);
+ }
+
+ //
+ // Send the print string to a Serial Port
+ //
+ SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
+}
+
+/**
+ Prints a debug message to the debug output device if the specified
+ error level is enabled.
+
+ If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
+ GetDebugPrintErrorLevel (), then print the message specified by Format and
+ the associated variable argument list to the debug output device.
+
+ If Format is NULL, then ASSERT().
+
+ @param ErrorLevel The error level of the debug message.
+ @param Format Format string for the debug message to print.
+ @param VaListMarker VA_LIST marker for the variable argument list.
+
+**/
+VOID
+EFIAPI
+DebugVPrint (
+ IN UINTN ErrorLevel,
+ IN CONST CHAR8 *Format,
+ IN VA_LIST VaListMarker
+ )
+{
+ DebugPrintMarker (ErrorLevel, Format, VaListMarker, NULL);
+}
+
+/**
+ Prints a debug message to the debug output device if the specified
+ error level is enabled.
+ This function use BASE_LIST which would provide a more compatible
+ service than VA_LIST.
+
+ If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
+ GetDebugPrintErrorLevel (), then print the message specified by Format and
+ the associated variable argument list to the debug output device.
+
+ If Format is NULL, then ASSERT().
+
+ @param ErrorLevel The error level of the debug message.
+ @param Format Format string for the debug message to print.
+ @param BaseListMarker BASE_LIST marker for the variable argument list.
+
+**/
+VOID
+EFIAPI
+DebugBPrint (
+ IN UINTN ErrorLevel,
+ IN CONST CHAR8 *Format,
+ IN BASE_LIST BaseListMarker
+ )
+{
+ DebugPrintMarker (ErrorLevel, Format, mVaListNull, BaseListMarker);
+}
+
+/**
+ Convert an UINT32 value into HEX string specified by Buffer.
+
+ @param Value The HEX value to convert to string
+ @param Buffer The pointer to the target buffer to be filled with HEX string
+
+**/
+VOID
+FillHex (
+ UINT32 Value,
+ CHAR8 *Buffer
+ )
+{
+ INTN Idx;
+ for (Idx = 7; Idx >= 0; Idx--) {
+ Buffer[Idx] = mHexTable[Value & 0x0F];
+ Value >>= 4;
+ }
+}
+
+/**
+ Prints an assert message containing a filename, line number, and description.
+ This may be followed by a breakpoint or a dead loop.
+
+ Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
+ to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
+ PcdDebugPropertyMask is set then CpuBreakpoint() is called. Otherwise, if
+ DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugPropertyMask is set then
+ CpuDeadLoop() is called. If neither of these bits are set, then this function
+ returns immediately after the message is printed to the debug output device.
+ DebugAssert() must actively prevent recursion. If DebugAssert() is called while
+ processing another DebugAssert(), then DebugAssert() must return immediately.
+
+ If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
+ If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
+
+**/
+VOID
+DebugAssertInternal (
+ VOID
+ )
+{
+ CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
+ UINT32 *Frame;
+
+ Frame = (UINT32 *)GetStackFramePointer ();
+
+ //
+ // Generate the ASSERT() message in Ascii format
+ //
+ AsciiStrnCpyS (
+ Buffer,
+ sizeof(Buffer) / sizeof(CHAR8),
+ "-> EBP:0x00000000 EIP:0x00000000\n",
+ sizeof(Buffer) / sizeof(CHAR8) - 1
+ );
+ SerialPortWrite ((UINT8 *)"ASSERT DUMP:\n", 13);
+ while (Frame != NULL) {
+ FillHex ((UINT32)Frame, Buffer + 9);
+ FillHex (Frame[1], Buffer + 9 + 8 + 8);
+ SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
+ if ((Frame[0] > (UINT32)Frame) && (Frame[0] < (UINT32)Frame + 0x00100000)) {
+ Frame = (UINT32 *)Frame[0];
+ } else {
+ Frame = NULL;
+ }
+ }
+
+ //
+ // Dead loop
+ //
+ CpuDeadLoop ();
+}
+
+/**
+ Prints an assert message containing a filename, line number, and description.
+ This may be followed by a breakpoint or a dead loop.
+
+ Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
+ to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
+ PcdDebugPropertyMask is set then CpuBreakpoint() is called. Otherwise, if
+ DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugPropertyMask is set then
+ CpuDeadLoop() is called. If neither of these bits are set, then this function
+ returns immediately after the message is printed to the debug output device.
+ DebugAssert() must actively prevent recursion. If DebugAssert() is called while
+ processing another DebugAssert(), then DebugAssert() must return immediately.
+
+ If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
+ If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
+
+ @param FileName The pointer to the name of the source file that generated the assert condition.
+ @param LineNumber The line number in the source file that generated the assert condition
+ @param Description The pointer to the description of the assert condition.
+
+**/
+VOID
+EFIAPI
+DebugAssert (
+ IN CONST CHAR8 *FileName,
+ IN UINTN LineNumber,
+ IN CONST CHAR8 *Description
+ )
+{
+ DebugAssertInternal ();
+}
+
+
+/**
+ Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
+
+ This function fills Length bytes of Buffer with the value specified by
+ PcdDebugClearMemoryValue, and returns Buffer.
+
+ If Buffer is NULL, then ASSERT().
+ If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+ @param Buffer The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.
+ @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
+
+ @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue.
+
+**/
+VOID *
+EFIAPI
+DebugClearMemory (
+ OUT VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ return Buffer;
+}
+
+
+/**
+ Returns TRUE if ASSERT() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
+ PcdDebugPropertyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugPropertyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugPropertyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugAssertEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);
+}
+
+
+/**
+ Returns TRUE if DEBUG() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
+ PcdDebugPropertyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugPropertyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugPropertyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugPrintEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
+}
+
+/**
+ Returns TRUE if DEBUG_CODE() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
+ PcdDebugPropertyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugPropertyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugPropertyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugCodeEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);
+}
+
+
+/**
+ Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
+ PcdDebugPropertyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugPropertyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugPropertyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugClearMemoryEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);
+}
+
+/**
+ Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel.
+
+ This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel.
+
+ @retval TRUE Current ErrorLevel is supported.
+ @retval FALSE Current ErrorLevel is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DebugPrintLevelEnabled (
+ IN CONST UINTN ErrorLevel
+ )
+{
+ return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.nasm
new file mode 100644
index 00000000..4143ab17
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.nasm
@@ -0,0 +1,25 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Abstract:
+;
+; FSP Debug functions
+;
+;------------------------------------------------------------------------------
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; UINT32 *
+; EFIAPI
+; GetStackFramePointer (
+; VOID
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(GetStackFramePointer)
+ASM_PFX(GetStackFramePointer):
+ mov eax, ebp
+ ret
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
new file mode 100644
index 00000000..262b3981
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Instance of FspPlatformLib
+#
+# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseFspPlatformLib
+ FILE_GUID = B6380BFB-7140-4C52-AC42-8C966C9A3F34
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FspPlatformLib
+
+[Sources]
+ FspPlatformMemory.c
+ FspPlatformNotify.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ MemoryAllocationLib
+ FspCommonLib
+ PerformanceLib
+ ReportStatusCodeLib
+
+[Guids]
+ gFspPerformanceDataGuid ## CONSUMES ## GUID
+ gFspEventEndOfFirmwareGuid ## PRODUCES ## GUID
+ gEfiEventReadyToBootGuid ## CONSUMES ## Event
+
+[Protocols]
+ gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformMemory.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformMemory.c
new file mode 100644
index 00000000..aa26ba94
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformMemory.c
@@ -0,0 +1,116 @@
+/** @file
+
+ Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/FspCommonLib.h>
+#include <FspGlobalData.h>
+#include <FspEas.h>
+
+/**
+ Get system memory resource descriptor by owner.
+
+ @param[in] OwnerGuid resource owner guid
+**/
+EFI_HOB_RESOURCE_DESCRIPTOR *
+EFIAPI
+FspGetResourceDescriptorByOwner (
+ IN EFI_GUID *OwnerGuid
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+
+ //
+ // Get the HOB list for processing
+ //
+ Hob.Raw = GetHobList ();
+
+ //
+ // Collect memory ranges
+ //
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) && \
+ (CompareGuid (&Hob.ResourceDescriptor->Owner, OwnerGuid))) {
+ return Hob.ResourceDescriptor;
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+
+ return NULL;
+}
+
+/**
+ Get system memory from HOB.
+
+ @param[in,out] LowMemoryLength less than 4G memory length
+ @param[in,out] HighMemoryLength greater than 4G memory length
+**/
+VOID
+EFIAPI
+FspGetSystemMemorySize (
+ IN OUT UINT64 *LowMemoryLength,
+ IN OUT UINT64 *HighMemoryLength
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;
+ EFI_PEI_HOB_POINTERS Hob;
+
+ ResourceAttribute = (
+ 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
+ );
+
+ Status = PeiServicesGetBootMode (&BootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ ResourceAttribute |= EFI_RESOURCE_ATTRIBUTE_TESTED;
+ }
+
+ *HighMemoryLength = 0;
+ *LowMemoryLength = SIZE_1MB;
+ //
+ // Get the HOB list for processing
+ //
+ Hob.Raw = GetHobList ();
+
+ //
+ // Collect memory ranges
+ //
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) ||
+ ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) &&
+ (Hob.ResourceDescriptor->ResourceAttribute == ResourceAttribute))) {
+ //
+ // Need memory above 1MB to be collected here
+ //
+ if (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB &&
+ Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) BASE_4GB) {
+ *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
+ } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) BASE_4GB) {
+ *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);
+ }
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformNotify.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformNotify.c
new file mode 100644
index 00000000..48cd6597
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformNotify.c
@@ -0,0 +1,409 @@
+/** @file
+
+ Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/FspSwitchStackLib.h>
+#include <Library/FspCommonLib.h>
+#include <Guid/EventGroup.h>
+#include <FspEas.h>
+#include <FspStatusCode.h>
+#include <Protocol/PciEnumerationComplete.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PerformanceLib.h>
+extern EFI_GUID gFspPerformanceDataGuid;
+
+EFI_PEI_PPI_DESCRIPTOR mPeiPostPciEnumerationPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPciEnumerationCompleteProtocolGuid,
+ NULL
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPeiReadyToBootPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEventReadyToBootGuid,
+ NULL
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPeiEndOfFirmwarePpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gFspEventEndOfFirmwareGuid,
+ NULL
+};
+
+UINT32 mFspNotifySequence[] = {
+ EnumInitPhaseAfterPciEnumeration,
+ EnumInitPhaseReadyToBoot,
+ EnumInitPhaseEndOfFirmware
+};
+
+/**
+ Install FSP notification.
+
+ @param[in] NotificationCode FSP notification code
+
+ @retval EFI_SUCCESS Notify FSP successfully
+ @retval EFI_INVALID_PARAMETER NotificationCode is invalid
+
+**/
+EFI_STATUS
+EFIAPI
+FspNotificationHandler (
+ IN UINT32 NotificationCode
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (NotificationCode) {
+ case EnumInitPhaseAfterPciEnumeration:
+ //
+ // Do POST PCI initialization if needed
+ //
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n"));
+ PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi);
+ break;
+
+ case EnumInitPhaseReadyToBoot:
+ //
+ // Ready To Boot
+ //
+ DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n"));
+ PeiServicesInstallPpi (&mPeiReadyToBootPpi);
+ break;
+
+ case EnumInitPhaseEndOfFirmware:
+ //
+ // End of Firmware
+ //
+ DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP End of Firmware ...\n"));
+ PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi);
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ This function transfer control back to BootLoader after FspSiliconInit.
+
+ @param[in] Status return status for the FspSiliconInit.
+
+**/
+VOID
+EFIAPI
+FspSiliconInitDone2 (
+ IN EFI_STATUS Status
+ )
+{
+ volatile EFI_STATUS FspStatus;
+
+ FspStatus = Status;
+ //
+ // Convert to FSP EAS defined API return codes
+ //
+ switch (Status) {
+ case EFI_SUCCESS:
+ case EFI_INVALID_PARAMETER:
+ case EFI_UNSUPPORTED:
+ case EFI_DEVICE_ERROR:
+ break;
+ default:
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() Invalid Error - [Status: 0x%08X]\n", Status));
+ Status = EFI_DEVICE_ERROR; // Force to known error.
+ break;
+ }
+ //
+ // This is the end of the FspSiliconInit API
+ // Give control back to the boot loader
+ //
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT);
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - [Status: 0x%08X] - End\n", Status));
+ PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {
+ do {
+ SetFspApiReturnStatus (Status);
+ Pei2LoaderSwitchStack ();
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "!!!ERROR: FspSiliconInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status));
+ }
+ } while (FspStatus != EFI_SUCCESS);
+ }
+}
+
+/**
+ This function returns control to BootLoader after MemoryInitApi.
+
+ @param[in] Status return status for the MemoryInitApi.
+ @param[in,out] HobListPtr The address of HobList pointer, if NULL, will get value from GetFspApiParameter2 ()
+**/
+VOID
+EFIAPI
+FspMemoryInitDone2 (
+ IN EFI_STATUS Status,
+ IN OUT VOID **HobListPtr
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+ volatile EFI_STATUS FspStatus;
+
+ FspStatus = Status;
+ //
+ // Calling use FspMemoryInit API
+ // Update HOB and return the control directly
+ //
+ if (HobListPtr == NULL) {
+ HobListPtr = (VOID **)GetFspApiParameter2 ();
+ }
+ if (HobListPtr != NULL) {
+ *HobListPtr = (VOID *) GetHobList ();
+ }
+ //
+ // Convert to FSP EAS defined API return codes
+ //
+ switch (Status) {
+ case EFI_SUCCESS:
+ case EFI_INVALID_PARAMETER:
+ case EFI_UNSUPPORTED:
+ case EFI_DEVICE_ERROR:
+ case EFI_OUT_OF_RESOURCES:
+ break;
+ default:
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() Invalid Error [Status: 0x%08X]\n", Status));
+ Status = EFI_DEVICE_ERROR; // Force to known error.
+ break;
+ }
+ //
+ // This is the end of the FspMemoryInit API
+ // Give control back to the boot loader
+ //
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() - [Status: 0x%08X] - End\n", Status));
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT);
+ FspData = GetFspGlobalDataPointer ();
+ PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[0] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_TEMP_RAM_INIT | FSP_STATUS_CODE_COMMON_CODE| FSP_STATUS_CODE_API_ENTRY);
+ PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[1] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_TEMP_RAM_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, (FspData->PerfData[2] & FSP_PERFORMANCE_DATA_TIMER_MASK), FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {
+ do {
+ SetFspApiReturnStatus (Status);
+ Pei2LoaderSwitchStack ();
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "!!!ERROR: FspMemoryInitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status));
+ }
+ } while (FspStatus != EFI_SUCCESS);
+ }
+
+ //
+ // The TempRamExitApi is called
+ //
+ if (GetFspApiCallingIndex () == TempRamExitApiIndex) {
+ SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT);
+ SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY);
+ PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - Begin\n"));
+ } else {
+ SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);
+ PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - Begin\n"));
+ }
+}
+
+/**
+ This function returns control to BootLoader after TempRamExitApi.
+
+ @param[in] Status return status for the TempRamExitApi.
+
+**/
+VOID
+EFIAPI
+FspTempRamExitDone2 (
+ IN EFI_STATUS Status
+ )
+{
+ //
+ volatile EFI_STATUS FspStatus;
+
+ FspStatus = Status;
+ // Convert to FSP EAS defined API return codes
+ //
+ switch (Status) {
+ case EFI_SUCCESS:
+ case EFI_INVALID_PARAMETER:
+ case EFI_UNSUPPORTED:
+ case EFI_DEVICE_ERROR:
+ break;
+ default:
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() Invalid Error - [Status: 0x%08X]\n", Status));
+ Status = EFI_DEVICE_ERROR; // Force to known error.
+ break;
+ }
+ //
+ // This is the end of the TempRamExit API
+ // Give control back to the boot loader
+ //
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - [Status: 0x%08X] - End\n", Status));
+ SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT);
+ PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {
+ do {
+ SetFspApiReturnStatus (Status);
+ Pei2LoaderSwitchStack ();
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "!!!ERROR: TempRamExitApi() - [Status: 0x%08X] - Error encountered during previous API and cannot proceed further\n", Status));
+ }
+ } while (FspStatus != EFI_SUCCESS);
+ }
+ SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT);
+ SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY);
+ PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n"));
+}
+
+/**
+ This function handle NotifyPhase API call from the BootLoader.
+ It gives control back to the BootLoader after it is handled. If the
+ Notification code is a ReadyToBoot event, this function will return
+ and FSP continues the remaining execution until it reaches the DxeIpl.
+
+**/
+VOID
+FspWaitForNotify (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NotificationValue;
+ UINT32 NotificationCount;
+ UINT8 Count;
+ volatile EFI_STATUS FspStatus;
+
+ NotificationCount = 0;
+ while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) {
+
+ Count = (UINT8)((NotificationCount << 1) & 0x07);
+ SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + Count);
+
+ if (NotificationCount == 0) {
+ SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION);
+ PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ } else if (NotificationCount == 1) {
+ SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION);
+ PERF_START_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ } else if (NotificationCount == 2) {
+ SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION);
+ PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY);
+ }
+
+ NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase;
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - Begin [Phase: %08X]\n", NotificationValue));
+ if (mFspNotifySequence[NotificationCount] != NotificationValue) {
+ //
+ // Notify code does not follow the predefined order
+ //
+ DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n"));
+ Status = EFI_UNSUPPORTED;
+ } else {
+ //
+ // Process Notification and Give control back to the boot loader framework caller
+ //
+ Status = FspNotificationHandler (NotificationValue);
+ if (!EFI_ERROR(Status)) {
+ NotificationCount++;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - End [Status: 0x%08X]\n", Status));
+ SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT + Count);
+
+ if ((NotificationCount - 1) == 0) {
+ PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ } else if ((NotificationCount - 1) == 1) {
+ PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ } else if ((NotificationCount - 1) == 2) {
+ PERF_END_EX(&gFspPerformanceDataGuid, "EventRec", NULL, 0, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT);
+ }
+ if (GetFspGlobalDataPointer ()->FspMode == FSP_IN_API_MODE) {
+ FspStatus = Status;
+ do {
+ SetFspApiReturnStatus(Status);
+ Pei2LoaderSwitchStack();
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "!!!ERROR: NotifyPhaseApi() [Phase: %08X] - Failed - [Status: 0x%08X]\n", NotificationValue, Status));
+ }
+ } while (FspStatus != EFI_SUCCESS);
+ }
+ }
+ //
+ // Control goes back to the PEI Core and it dispatches further PEIMs.
+ // DXEIPL is the final one to transfer control back to the boot loader.
+ //
+}
+
+/**
+ This function transfer control back to BootLoader after FspSiliconInit.
+
+**/
+VOID
+EFIAPI
+FspSiliconInitDone (
+ VOID
+ )
+{
+ FspSiliconInitDone2 (EFI_SUCCESS);
+}
+
+/**
+ This function returns control to BootLoader after MemoryInitApi.
+
+ @param[in,out] HobListPtr The address of HobList pointer.
+**/
+VOID
+EFIAPI
+FspMemoryInitDone (
+ IN OUT VOID **HobListPtr
+ )
+{
+ FspMemoryInitDone2 (EFI_SUCCESS, HobListPtr);
+}
+
+/**
+ This function returns control to BootLoader after TempRamExitApi.
+
+**/
+VOID
+EFIAPI
+FspTempRamExitDone (
+ VOID
+ )
+{
+ FspTempRamExitDone2 (EFI_SUCCESS);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
new file mode 100644
index 00000000..5f164b5a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
@@ -0,0 +1,33 @@
+## @file
+# Instance of BaseFspSwitchStackLib
+#
+# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseFspSwitchStackLib
+ FILE_GUID = 68E79161-F7CE-4A61-8C72-F4DF6FF35CAA
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FspSwitchStackLib
+
+[Sources.IA32]
+ FspSwitchStackLib.c
+
+[Sources.IA32]
+ Ia32/Stack.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+
+[LibraryClasses]
+ BaseLib
+ IoLib
+
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c
new file mode 100644
index 00000000..27bfdb86
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c
@@ -0,0 +1,36 @@
+/** @file
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/FspCommonLib.h>
+
+/**
+
+ Switch the current stack to the previous saved stack.
+
+ @param[in] NewStack The new stack to be switched.
+
+ @return OldStack After switching to the saved stack,
+ this value will be saved in eax before returning.
+
+
+**/
+UINT32
+SwapStack (
+ IN UINT32 NewStack
+ )
+{
+ FSP_GLOBAL_DATA *FspData;
+ UINT32 OldStack;
+
+ FspData = GetFspGlobalDataPointer ();
+ OldStack = FspData->CoreStack;
+ FspData->CoreStack = NewStack;
+ return OldStack;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/Ia32/Stack.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/Ia32/Stack.nasm
new file mode 100644
index 00000000..deb7647d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/Ia32/Stack.nasm
@@ -0,0 +1,68 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2016 - 2019, 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
+
+extern ASM_PFX(SwapStack)
+
+;------------------------------------------------------------------------------
+; UINT32
+; EFIAPI
+; Pei2LoaderSwitchStack (
+; VOID
+; )
+;------------------------------------------------------------------------------
+global ASM_PFX(Pei2LoaderSwitchStack)
+ASM_PFX(Pei2LoaderSwitchStack):
+ xor eax, eax
+ jmp ASM_PFX(FspSwitchStack)
+
+;------------------------------------------------------------------------------
+; UINT32
+; EFIAPI
+; Loader2PeiSwitchStack (
+; VOID
+; )
+;------------------------------------------------------------------------------
+global ASM_PFX(Loader2PeiSwitchStack)
+ASM_PFX(Loader2PeiSwitchStack):
+ jmp ASM_PFX(FspSwitchStack)
+
+;------------------------------------------------------------------------------
+; UINT32
+; EFIAPI
+; FspSwitchStack (
+; VOID
+; )
+;------------------------------------------------------------------------------
+global ASM_PFX(FspSwitchStack)
+ASM_PFX(FspSwitchStack):
+ ; Save current contexts
+ push eax
+ pushfd
+ cli
+ pushad
+ sub esp, 8
+ sidt [esp]
+
+ ; Load new stack
+ push esp
+ call ASM_PFX(SwapStack)
+ mov esp, eax
+
+ ; Restore previous contexts
+ lidt [esp]
+ add esp, 8
+ popad
+ popfd
+ add esp, 4
+ ret
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/Flat32.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/Flat32.nasm
new file mode 100644
index 00000000..e004de2d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/Flat32.nasm
@@ -0,0 +1,121 @@
+;; @file
+; This is the code that goes from real-mode to protected mode.
+; It consumes the reset vector, configures the stack.
+;
+; Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+;
+; Define assembler characteristics
+;
+
+extern ASM_PFX(TempRamInitApi)
+
+SECTION .text
+
+%macro RET_ESI 0
+
+ movd esi, mm7 ; restore ESP from MM7
+ jmp esi
+
+%endmacro
+
+;
+; Perform early platform initialization
+;
+global ASM_PFX(SecPlatformInit)
+ASM_PFX(SecPlatformInit):
+
+ RET_ESI
+
+;
+; 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 initialisation
+; Setup a stack
+;
+;----------------------------------------------------------------------------
+global ASM_PFX(ProtectedModeEntryPoint)
+ASM_PFX(ProtectedModeEntryPoint):
+ ;
+ ; Dummy function. Consume 2 API to make sure they can be linked.
+ ;
+ mov eax, ASM_PFX(TempRamInitApi)
+
+ ; Should never return
+ jmp $
+
+;
+; ROM-based Global-Descriptor Table for the 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 code segment descriptor
+;
+LINEAR_CODE_SEL equ $ - GDT_BASE ; Selector [0x8]
+ DW 0FFFFh ; limit 0xFFFF
+ 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 [0x10]
+ DW 0FFFFh ; limit 0xFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 093h ; present, ring 0, data, expand-up, not-writable
+ DB 0CFh ; 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
+
+global ASM_PFX(ProtectedModeEntryLinearAddress)
+global ASM_PFX(ProtectedModeEntryLinearOffset)
+
+ASM_PFX(ProtectedModeEntryLinearAddress):
+ASM_PFX(ProtectedModeEntryLinearOffset):
+ DD ASM_PFX(ProtectedModeEntryPoint) ; Offset of our 32 bit code
+ DW LINEAR_CODE_SEL
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/SecCarInit.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/SecCarInit.nasm
new file mode 100644
index 00000000..121f2b0c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/SecCarInit.nasm
@@ -0,0 +1,40 @@
+;; @file
+; SEC CAR function
+;
+; Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;;
+
+;
+; Define assembler characteristics
+;
+
+%macro RET_ESI 0
+
+ movd esi, mm7 ; move ReturnAddress from MM7 to ESI
+ jmp esi
+
+%endmacro
+
+SECTION .text
+
+;-----------------------------------------------------------------------------
+;
+; Section: SecCarInit
+;
+; Description: This function initializes the Cache for Data, Stack, and Code
+;
+;-----------------------------------------------------------------------------
+global ASM_PFX(SecCarInit)
+ASM_PFX(SecCarInit):
+
+ ;
+ ; Set up CAR
+ ;
+
+ xor eax, eax
+
+SecCarInitExit:
+
+ RET_ESI
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/PlatformSecLibNull.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/PlatformSecLibNull.c
new file mode 100644
index 00000000..09539f4b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/PlatformSecLibNull.c
@@ -0,0 +1,44 @@
+/** @file
+ Null instance of Platform Sec Lib.
+
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/FspCommonLib.h>
+
+/**
+ This function check the signature of UPD.
+
+ @param[in] ApiIdx Internal index of the FSP API.
+ @param[in] ApiParam Parameter of the FSP API.
+
+**/
+EFI_STATUS
+EFIAPI
+FspUpdSignatureCheck (
+ IN UINT32 ApiIdx,
+ IN VOID *ApiParam
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ This function handles FspMultiPhaseSiInitApi.
+
+ @param[in] ApiIdx Internal index of the FSP API.
+ @param[in] ApiParam Parameter of the FSP API.
+
+**/
+EFI_STATUS
+EFIAPI
+FspMultiPhaseSiInitApiHandler (
+ IN UINT32 ApiIdx,
+ IN VOID *ApiParam
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf
new file mode 100644
index 00000000..04129844
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf
@@ -0,0 +1,51 @@
+## @file
+# NULL instance of Platform Sec Lib.
+#
+# 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 = BaseFspSecPlatformLibNull
+ FILE_GUID = C128CADC-623E-4E41-97CB-A7138E627460
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FspSecPlatformLib
+
+#
+# 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]
+ PlatformSecLibNull.c
+
+[Sources.IA32]
+ Ia32/Flat32.nasm
+ Ia32/SecCarInit.nasm
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Readme.md b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Readme.md
new file mode 100644
index 00000000..c8d5eae2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Readme.md
@@ -0,0 +1,7 @@
+# IntelFsp2Pkg
+
+This package provides the component to create an FSP binary.
+
+Source Repository: https://github.com/tianocore/edk2/tree/master/IntelFsp2Pkg
+
+A whitepaper to describe the IntelFsp2Pkg: https://firmware.intel.com/sites/default/files/A_Tour_Beyond_BIOS_Creating_the_Intel_Firmware_Support_Package_with_the_EFI_Developer_Kit_II_%28FSP2.0%29.pdf
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py
new file mode 100755
index 00000000..b3f2a3e5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py
@@ -0,0 +1,884 @@
+#!/usr/bin/env python
+## @ FspDscBsf2Yaml.py
+# This script convert DSC or BSF format file into YAML format
+#
+# Copyright(c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+import os
+import re
+import sys
+from datetime import date
+from collections import OrderedDict
+from functools import reduce
+
+from GenCfgOpt import CGenCfgOpt
+
+__copyright_tmp__ = """## @file
+#
+# YAML CFGDATA %s File.
+#
+# Copyright(c) %4d, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+"""
+
+__copyright_dsc__ = """## @file
+#
+# Copyright (c) %04d, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[PcdsDynamicVpd.Upd]
+ #
+ # Global definitions in BSF
+ # !BSF BLOCK:{NAME:"FSP UPD Configuration", VER:"0.1"}
+ #
+
+"""
+
+
+def Bytes2Val(Bytes):
+ return reduce(lambda x, y: (x << 8) | y, Bytes[::-1])
+
+
+def Str2Bytes(Value, Blen):
+ Result = bytearray(Value[1:-1], 'utf-8') # Excluding quotes
+ if len(Result) < Blen:
+ Result.extend(b'\x00' * (Blen - len(Result)))
+ return Result
+
+
+class CFspBsf2Dsc:
+
+ def __init__(self, bsf_file):
+ self.cfg_list = CFspBsf2Dsc.parse_bsf(bsf_file)
+
+ def get_dsc_lines(self):
+ return CFspBsf2Dsc.generate_dsc(self.cfg_list)
+
+ def save_dsc(self, dsc_file):
+ return CFspBsf2Dsc.generate_dsc(self.cfg_list, dsc_file)
+
+ @staticmethod
+ def parse_bsf(bsf_file):
+
+ fd = open(bsf_file, 'r')
+ bsf_txt = fd.read()
+ fd.close()
+
+ find_list = []
+ regex = re.compile(r'\s+Find\s+"(.*?)"(.*?)^\s+\$(.*?)\s+', re.S | re.MULTILINE)
+ for match in regex.finditer(bsf_txt):
+ find = match.group(1)
+ name = match.group(3)
+ if not name.endswith('_Revision'):
+ raise Exception("Unexpected CFG item following 'Find' !")
+ find_list.append((name, find))
+
+ idx = 0
+ count = 0
+ prefix = ''
+ chk_dict = {}
+ cfg_list = []
+ cfg_temp = {'find': '', 'cname': '', 'length': 0, 'value': '0', 'type': 'Reserved',
+ 'embed': '', 'page': '', 'option': '', 'instance': 0}
+ regex = re.compile(r'^\s+(\$(.*?)|Skip)\s+(\d+)\s+bytes(\s+\$_DEFAULT_\s+=\s+(.+?))?$',
+ re.S | re.MULTILINE)
+
+ for match in regex.finditer(bsf_txt):
+ dlen = int(match.group(3))
+ if match.group(1) == 'Skip':
+ key = 'gPlatformFspPkgTokenSpaceGuid_BsfSkip%d' % idx
+ val = ', '.join(['%02X' % ord(i) for i in '\x00' * dlen])
+ idx += 1
+ option = '$SKIP'
+ else:
+ key = match.group(2)
+ val = match.group(5)
+ option = ''
+
+ cfg_item = dict(cfg_temp)
+ finds = [i for i in find_list if i[0] == key]
+ if len(finds) > 0:
+ if count >= 1:
+ # Append a dummy one
+ cfg_item['cname'] = 'Dummy'
+ cfg_list.append(dict(cfg_item))
+ cfg_list[-1]['embed'] = '%s:TAG_%03X:END' % (prefix, ord(prefix[-1]))
+ prefix = finds[0][1]
+ cfg_item['embed'] = '%s:TAG_%03X:START' % (prefix, ord(prefix[-1]))
+ cfg_item['find'] = prefix
+ cfg_item['cname'] = 'Signature'
+ cfg_item['length'] = len(finds[0][1])
+ str2byte = Str2Bytes("'" + finds[0][1] + "'", len(finds[0][1]))
+ cfg_item['value'] = '0x%X' % Bytes2Val(str2byte)
+ cfg_list.append(dict(cfg_item))
+ cfg_item = dict(cfg_temp)
+ find_list.pop(0)
+ count = 0
+
+ cfg_item['cname'] = key
+ cfg_item['length'] = dlen
+ cfg_item['value'] = val
+ cfg_item['option'] = option
+
+ if key not in chk_dict.keys():
+ chk_dict[key] = 0
+ else:
+ chk_dict[key] += 1
+ cfg_item['instance'] = chk_dict[key]
+
+ cfg_list.append(cfg_item)
+ count += 1
+
+ if prefix:
+ cfg_item = dict(cfg_temp)
+ cfg_item['cname'] = 'Dummy'
+ cfg_item['embed'] = '%s:%03X:END' % (prefix, ord(prefix[-1]))
+ cfg_list.append(cfg_item)
+
+ option_dict = {}
+ selreg = re.compile(r'\s+Selection\s*(.+?)\s*,\s*"(.*?)"$', re.S | re.MULTILINE)
+ regex = re.compile(r'^List\s&(.+?)$(.+?)^EndList$', re.S | re.MULTILINE)
+ for match in regex.finditer(bsf_txt):
+ key = match.group(1)
+ option_dict[key] = []
+ for select in selreg.finditer(match.group(2)):
+ option_dict[key].append((int(select.group(1), 0), select.group(2)))
+
+ chk_dict = {}
+ pagereg = re.compile(r'^Page\s"(.*?)"$(.+?)^EndPage$', re.S | re.MULTILINE)
+ for match in pagereg.finditer(bsf_txt):
+ page = match.group(1)
+ for line in match.group(2).splitlines():
+ match = re.match(r'\s+(Combo|EditNum)\s\$(.+?),\s"(.*?)",\s(.+?),$', line)
+ if match:
+ cname = match.group(2)
+ if cname not in chk_dict.keys():
+ chk_dict[cname] = 0
+ else:
+ chk_dict[cname] += 1
+ instance = chk_dict[cname]
+ cfg_idxs = [i for i, j in enumerate(cfg_list) if j['cname'] == cname and j['instance'] == instance]
+ if len(cfg_idxs) != 1:
+ raise Exception("Multiple CFG item '%s' found !" % cname)
+ cfg_item = cfg_list[cfg_idxs[0]]
+ cfg_item['page'] = page
+ cfg_item['type'] = match.group(1)
+ cfg_item['prompt'] = match.group(3)
+ cfg_item['range'] = None
+ if cfg_item['type'] == 'Combo':
+ cfg_item['option'] = option_dict[match.group(4)[1:]]
+ elif cfg_item['type'] == 'EditNum':
+ cfg_item['option'] = match.group(4)
+ match = re.match(r'\s+ Help\s"(.*?)"$', line)
+ if match:
+ cfg_item['help'] = match.group(1)
+
+ match = re.match(r'\s+"Valid\srange:\s(.*)"$', line)
+ if match:
+ parts = match.group(1).split()
+ cfg_item['option'] = (
+ (int(parts[0], 0), int(parts[2], 0), cfg_item['option']))
+
+ return cfg_list
+
+ @staticmethod
+ def generate_dsc(option_list, dsc_file=None):
+ dsc_lines = []
+ header = '%s' % (__copyright_dsc__ % date.today().year)
+ dsc_lines.extend(header.splitlines())
+
+ pages = []
+ for cfg_item in option_list:
+ if cfg_item['page'] and (cfg_item['page'] not in pages):
+ pages.append(cfg_item['page'])
+
+ page_id = 0
+ for page in pages:
+ dsc_lines.append(' # !BSF PAGES:{PG%02X::"%s"}' % (page_id, page))
+ page_id += 1
+ dsc_lines.append('')
+
+ last_page = ''
+ for option in option_list:
+ dsc_lines.append('')
+ default = option['value']
+ pos = option['cname'].find('_')
+ name = option['cname'][pos + 1:]
+
+ if option['find']:
+ dsc_lines.append(' # !BSF FIND:{%s}' % option['find'])
+ dsc_lines.append('')
+
+ if option['instance'] > 0:
+ name = name + '_%s' % option['instance']
+
+ if option['embed']:
+ dsc_lines.append(' # !HDR EMBED:{%s}' % option['embed'])
+
+ if option['type'] == 'Reserved':
+ dsc_lines.append(' # !BSF NAME:{Reserved} TYPE:{Reserved}')
+ if option['option'] == '$SKIP':
+ dsc_lines.append(' # !BSF OPTION:{$SKIP}')
+ else:
+ prompt = option['prompt']
+
+ if last_page != option['page']:
+ last_page = option['page']
+ dsc_lines.append(' # !BSF PAGE:{PG%02X}' % (pages.index(option['page'])))
+
+ if option['type'] == 'Combo':
+ dsc_lines.append(' # !BSF NAME:{%s} TYPE:{%s}' %
+ (prompt, option['type']))
+ ops = []
+ for val, text in option['option']:
+ ops.append('0x%x:%s' % (val, text))
+ dsc_lines.append(' # !BSF OPTION:{%s}' % (', '.join(ops)))
+ elif option['type'] == 'EditNum':
+ cfg_len = option['length']
+ if ',' in default and cfg_len > 8:
+ dsc_lines.append(' # !BSF NAME:{%s} TYPE:{Table}' % (prompt))
+ if cfg_len > 16:
+ cfg_len = 16
+ ops = []
+ for i in range(cfg_len):
+ ops.append('%X:1:HEX' % i)
+ dsc_lines.append(' # !BSF OPTION:{%s}' % (', '.join(ops)))
+ else:
+ dsc_lines.append(
+ ' # !BSF NAME:{%s} TYPE:{%s, %s,(0x%X, 0x%X)}' %
+ (prompt, option['type'], option['option'][2],
+ option['option'][0], option['option'][1]))
+ dsc_lines.append(' # !BSF HELP:{%s}' % option['help'])
+
+ if ',' in default:
+ default = '{%s}' % default
+ dsc_lines.append(' gCfgData.%-30s | * | 0x%04X | %s' %
+ (name, option['length'], default))
+
+ if dsc_file:
+ fd = open(dsc_file, 'w')
+ fd.write('\n'.join(dsc_lines))
+ fd.close()
+
+ return dsc_lines
+
+
+class CFspDsc2Yaml():
+
+ def __init__(self):
+ self._Hdr_key_list = ['EMBED', 'STRUCT']
+ self._Bsf_key_list = ['NAME', 'HELP', 'TYPE', 'PAGE', 'PAGES', 'OPTION',
+ 'CONDITION', 'ORDER', 'MARKER', 'SUBT', 'FIELD', 'FIND']
+ self.gen_cfg_data = None
+ self.cfg_reg_exp = re.compile(r"^([_a-zA-Z0-9$\(\)]+)\s*\|\s*(0x[0-9A-F]+|\*)\s*\|"
+ + r"\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)")
+ self.bsf_reg_exp = re.compile(r"(%s):{(.+?)}(?:$|\s+)" % '|'.join(self._Bsf_key_list))
+ self.hdr_reg_exp = re.compile(r"(%s):{(.+?)}" % '|'.join(self._Hdr_key_list))
+ self.prefix = ''
+ self.unused_idx = 0
+ self.offset = 0
+ self.base_offset = 0
+
+ def load_config_data_from_dsc(self, file_name):
+ """
+ Load and parse a DSC CFGDATA file.
+ """
+ gen_cfg_data = CGenCfgOpt('FSP')
+ if file_name.endswith('.dsc'):
+ # if gen_cfg_data.ParseDscFileYaml(file_name, '') != 0:
+ if gen_cfg_data.ParseDscFile(file_name, '') != 0:
+ raise Exception('DSC file parsing error !')
+ if gen_cfg_data.CreateVarDict() != 0:
+ raise Exception('DSC variable creation error !')
+ else:
+ raise Exception('Unsupported file "%s" !' % file_name)
+ self.gen_cfg_data = gen_cfg_data
+
+ def print_dsc_line(self):
+ """
+ Debug function to print all DSC lines.
+ """
+ for line in self.gen_cfg_data._DscLines:
+ print(line)
+
+ def format_value(self, field, text, indent=''):
+ """
+ Format a CFGDATA item into YAML format.
+ """
+ if(not text.startswith('!expand')) and (': ' in text):
+ tgt = ':' if field == 'option' else '- '
+ text = text.replace(': ', tgt)
+ lines = text.splitlines()
+ if len(lines) == 1 and field != 'help':
+ return text
+ else:
+ return '>\n ' + '\n '.join([indent + i.lstrip() for i in lines])
+
+ def reformat_pages(self, val):
+ # Convert XXX:YYY into XXX::YYY format for page definition
+ parts = val.split(',')
+ if len(parts) <= 1:
+ return val
+
+ new_val = []
+ for each in parts:
+ nodes = each.split(':')
+ if len(nodes) == 2:
+ each = '%s::%s' % (nodes[0], nodes[1])
+ new_val.append(each)
+ ret = ','.join(new_val)
+ return ret
+
+ def reformat_struct_value(self, utype, val):
+ # Convert DSC UINT16/32/64 array into new format by
+ # adding prefix 0:0[WDQ] to provide hint to the array format
+ if utype in ['UINT16', 'UINT32', 'UINT64']:
+ if val and val[0] == '{' and val[-1] == '}':
+ if utype == 'UINT16':
+ unit = 'W'
+ elif utype == 'UINT32':
+ unit = 'D'
+ else:
+ unit = 'Q'
+ val = '{ 0:0%s, %s }' % (unit, val[1:-1])
+ return val
+
+ def process_config(self, cfg):
+ if 'page' in cfg:
+ cfg['page'] = self.reformat_pages(cfg['page'])
+
+ if 'struct' in cfg:
+ cfg['value'] = self.reformat_struct_value(cfg['struct'], cfg['value'])
+
+ def parse_dsc_line(self, dsc_line, config_dict, init_dict, include):
+ """
+ Parse a line in DSC and update the config dictionary accordingly.
+ """
+ init_dict.clear()
+ match = re.match(r'g(CfgData|\w+FspPkgTokenSpaceGuid)\.(.+)', dsc_line)
+ if match:
+ match = self.cfg_reg_exp.match(match.group(2))
+ if not match:
+ return False
+ config_dict['cname'] = self.prefix + match.group(1)
+ value = match.group(4).strip()
+ length = match.group(3).strip()
+ config_dict['length'] = length
+ config_dict['value'] = value
+ if match.group(2) == '*':
+ self.offset += int(length, 0)
+ else:
+ org_offset = int(match.group(2), 0)
+ if org_offset == 0:
+ self.base_offset = self.offset
+ offset = org_offset + self.base_offset
+ if self.offset != offset:
+ if offset > self.offset:
+ init_dict['padding'] = offset - self.offset
+ self.offset = offset + int(length, 0)
+ return True
+
+ match = re.match(r"^\s*#\s+!([<>])\s+include\s+(.+)", dsc_line)
+ if match and len(config_dict) == 0:
+ # !include should not be inside a config field
+ # if so, do not convert include into YAML
+ init_dict = dict(config_dict)
+ config_dict.clear()
+ config_dict['cname'] = '$ACTION'
+ if match.group(1) == '<':
+ config_dict['include'] = match.group(2)
+ else:
+ config_dict['include'] = ''
+ return True
+
+ match = re.match(r"^\s*#\s+(!BSF|!HDR)\s+(.+)", dsc_line)
+ if not match:
+ return False
+
+ remaining = match.group(2)
+ if match.group(1) == '!BSF':
+ result = self.bsf_reg_exp.findall(remaining)
+ if not result:
+ return False
+
+ for each in result:
+ key = each[0].lower()
+ val = each[1]
+ if key == 'field':
+ name = each[1]
+ if ':' not in name:
+ raise Exception('Incorrect bit field format !')
+ parts = name.split(':')
+ config_dict['length'] = parts[1]
+ config_dict['cname'] = '@' + parts[0]
+ return True
+ elif key in ['pages', 'page', 'find']:
+ init_dict = dict(config_dict)
+ config_dict.clear()
+ config_dict['cname'] = '$ACTION'
+ if key == 'find':
+ config_dict['find'] = val
+ else:
+ config_dict['page'] = val
+ return True
+ elif key == 'subt':
+ config_dict.clear()
+ parts = each[1].split(':')
+ tmp_name = parts[0][:-5]
+ if tmp_name == 'CFGHDR':
+ cfg_tag = '_$FFF_'
+ sval = '!expand { %s_TMPL : [ ' % tmp_name + '%s, %s, ' % (parts[1], cfg_tag) \
+ + ', '.join(parts[2:]) + ' ] }'
+ else:
+ sval = '!expand { %s_TMPL : [ ' % tmp_name + ', '.join(parts[1:]) + ' ] }'
+ config_dict.clear()
+ config_dict['cname'] = tmp_name
+ config_dict['expand'] = sval
+ return True
+ else:
+ if key in ['name', 'help', 'option'] and val.startswith('+'):
+ val = config_dict[key] + '\n' + val[1:]
+ if val.strip() == '':
+ val = "''"
+ config_dict[key] = val
+
+ else:
+ match = self.hdr_reg_exp.match(remaining)
+ if not match:
+ return False
+ key = match.group(1)
+ remaining = match.group(2)
+ if key == 'EMBED':
+ parts = remaining.split(':')
+ names = parts[0].split(',')
+ if parts[-1] == 'END':
+ prefix = '>'
+ else:
+ prefix = '<'
+ skip = False
+ if parts[1].startswith('TAG_'):
+ tag_txt = '%s:%s' % (names[0], parts[1])
+ else:
+ tag_txt = names[0]
+ if parts[2] in ['START', 'END']:
+ if names[0] == 'PCIE_RP_PIN_CTRL[]':
+ skip = True
+ else:
+ tag_txt = '%s:%s' % (names[0], parts[1])
+ if not skip:
+ config_dict.clear()
+ config_dict['cname'] = prefix + tag_txt
+ return True
+
+ if key == 'STRUCT':
+ text = remaining.strip()
+ config_dict[key.lower()] = text
+
+ return False
+
+ def process_template_lines(self, lines):
+ """
+ Process a line in DSC template section.
+ """
+ template_name = ''
+ bsf_temp_dict = OrderedDict()
+ temp_file_dict = OrderedDict()
+ include_file = ['.']
+
+ for line in lines:
+ match = re.match(r"^\s*#\s+!([<>])\s+include\s+(.+)", line)
+ if match:
+ if match.group(1) == '<':
+ include_file.append(match.group(2))
+ else:
+ include_file.pop()
+
+ match = re.match(r"^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", line)
+ if match:
+ if match.group(3) == 'START' and not template_name:
+ template_name = match.group(2).strip()
+ temp_file_dict[template_name] = list(include_file)
+ bsf_temp_dict[template_name] = []
+ if match.group(3) == 'END' and (template_name == match.group(2).strip()) \
+ and template_name:
+ template_name = ''
+ else:
+ if template_name:
+ bsf_temp_dict[template_name].append(line)
+ return bsf_temp_dict, temp_file_dict
+
+ def process_option_lines(self, lines):
+ """
+ Process a line in DSC config section.
+ """
+ cfgs = []
+ struct_end = False
+ config_dict = dict()
+ init_dict = dict()
+ include = ['']
+ for line in lines:
+ ret = self.parse_dsc_line(line, config_dict, init_dict, include)
+ if ret:
+ if 'padding' in init_dict:
+ num = init_dict['padding']
+ init_dict.clear()
+ padding_dict = {}
+ cfgs.append(padding_dict)
+ padding_dict['cname'] = 'UnusedUpdSpace%d' % self.unused_idx
+ padding_dict['length'] = '0x%x' % num
+ padding_dict['value'] = '{ 0 }'
+ self.unused_idx += 1
+
+ if cfgs and cfgs[-1]['cname'][0] != '@' and config_dict['cname'][0] == '@':
+ # it is a bit field, mark the previous one as virtual
+ cname = cfgs[-1]['cname']
+ new_cfg = dict(cfgs[-1])
+ new_cfg['cname'] = '@$STRUCT'
+ cfgs[-1].clear()
+ cfgs[-1]['cname'] = cname
+ cfgs.append(new_cfg)
+
+ if cfgs and cfgs[-1]['cname'] == 'CFGHDR' and config_dict['cname'][0] == '<':
+ # swap CfgHeader and the CFG_DATA order
+ if ':' in config_dict['cname']:
+ # replace the real TAG for CFG_DATA
+ cfgs[-1]['expand'] = cfgs[-1]['expand'].replace(
+ '_$FFF_', '0x%s' %
+ config_dict['cname'].split(':')[1][4:])
+ cfgs.insert(-1, config_dict)
+ else:
+ self.process_config(config_dict)
+ if struct_end:
+ struct_end = False
+ cfgs.insert(-1, config_dict)
+ else:
+ cfgs.append(config_dict)
+ if config_dict['cname'][0] == '>':
+ struct_end = True
+
+ config_dict = dict(init_dict)
+ return cfgs
+
+ def variable_fixup(self, each):
+ """
+ Fix up some variable definitions for SBL.
+ """
+ key = each
+ val = self.gen_cfg_data._MacroDict[each]
+ return key, val
+
+ def template_fixup(self, tmp_name, tmp_list):
+ """
+ Fix up some special config templates for SBL
+ """
+ return
+
+ def config_fixup(self, cfg_list):
+ """
+ Fix up some special config items for SBL.
+ """
+
+ # Insert FSPT_UPD/FSPM_UPD/FSPS_UPD tag so as to create C strcture
+ idxs = []
+ for idx, cfg in enumerate(cfg_list):
+ if cfg['cname'].startswith('<FSP_UPD_HEADER'):
+ idxs.append(idx)
+
+ if len(idxs) != 3:
+ return
+
+ # Handle insert backwards so that the index does not change in the loop
+ fsp_comp = 'SMT'
+ idx_comp = 0
+ for idx in idxs[::-1]:
+ # Add current FSP?_UPD start tag
+ cfgfig_dict = {}
+ cfgfig_dict['cname'] = '<FSP%s_UPD' % fsp_comp[idx_comp]
+ cfg_list.insert(idx, cfgfig_dict)
+ if idx_comp < 2:
+ # Add previous FSP?_UPD end tag
+ cfgfig_dict = {}
+ cfgfig_dict['cname'] = '>FSP%s_UPD' % fsp_comp[idx_comp + 1]
+ cfg_list.insert(idx, cfgfig_dict)
+ idx_comp += 1
+
+ # Add final FSPS_UPD end tag
+ cfgfig_dict = {}
+ cfgfig_dict['cname'] = '>FSP%s_UPD' % fsp_comp[0]
+ cfg_list.append(cfgfig_dict)
+
+ return
+
+ def get_section_range(self, section_name):
+ """
+ Extract line number range from config file for a given section name.
+ """
+ start = -1
+ end = -1
+ for idx, line in enumerate(self.gen_cfg_data._DscLines):
+ if start < 0 and line.startswith('[%s]' % section_name):
+ start = idx
+ elif start >= 0 and line.startswith('['):
+ end = idx
+ break
+ if start == -1:
+ start = 0
+ if end == -1:
+ end = len(self.gen_cfg_data._DscLines)
+ return start, end
+
+ def normalize_file_name(self, file, is_temp=False):
+ """
+ Normalize file name convention so that it is consistent.
+ """
+ if file.endswith('.dsc'):
+ file = file[:-4] + '.yaml'
+ dir_name = os.path.dirname(file)
+ base_name = os.path.basename(file)
+ if is_temp:
+ if 'Template_' not in file:
+ base_name = base_name.replace('Template', 'Template_')
+ else:
+ if 'CfgData_' not in file:
+ base_name = base_name.replace('CfgData', 'CfgData_')
+ if dir_name:
+ path = dir_name + '/' + base_name
+ else:
+ path = base_name
+ return path
+
+ def output_variable(self):
+ """
+ Output variable block into a line list.
+ """
+ lines = []
+ for each in self.gen_cfg_data._MacroDict:
+ key, value = self.variable_fixup(each)
+ lines.append('%-30s : %s' % (key, value))
+ return lines
+
+ def output_template(self):
+ """
+ Output template block into a line list.
+ """
+ self.offset = 0
+ self.base_offset = 0
+ start, end = self.get_section_range('PcdsDynamicVpd.Tmp')
+ bsf_temp_dict, temp_file_dict = self.process_template_lines(self.gen_cfg_data._DscLines[start:end])
+ template_dict = dict()
+ lines = []
+ file_lines = {}
+ last_file = '.'
+ file_lines[last_file] = []
+
+ for tmp_name in temp_file_dict:
+ temp_file_dict[tmp_name][-1] = self.normalize_file_name(temp_file_dict[tmp_name][-1], True)
+ if len(temp_file_dict[tmp_name]) > 1:
+ temp_file_dict[tmp_name][-2] = self.normalize_file_name(temp_file_dict[tmp_name][-2], True)
+
+ for tmp_name in bsf_temp_dict:
+ file = temp_file_dict[tmp_name][-1]
+ if last_file != file and len(temp_file_dict[tmp_name]) > 1:
+ inc_file = temp_file_dict[tmp_name][-2]
+ file_lines[inc_file].extend(['', '- !include %s' % temp_file_dict[tmp_name][-1], ''])
+ last_file = file
+ if file not in file_lines:
+ file_lines[file] = []
+ lines = file_lines[file]
+ text = bsf_temp_dict[tmp_name]
+ tmp_list = self.process_option_lines(text)
+ self.template_fixup(tmp_name, tmp_list)
+ template_dict[tmp_name] = tmp_list
+ lines.append('%s: >' % tmp_name)
+ lines.extend(self.output_dict(tmp_list, False)['.'])
+ lines.append('\n')
+ return file_lines
+
+ def output_config(self):
+ """
+ Output config block into a line list.
+ """
+ self.offset = 0
+ self.base_offset = 0
+ start, end = self.get_section_range('PcdsDynamicVpd.Upd')
+ cfgs = self.process_option_lines(self.gen_cfg_data._DscLines[start:end])
+ self.config_fixup(cfgs)
+ file_lines = self.output_dict(cfgs, True)
+ return file_lines
+
+ def output_dict(self, cfgs, is_configs):
+ """
+ Output one config item into a line list.
+ """
+ file_lines = {}
+ level = 0
+ file = '.'
+ for each in cfgs:
+ if 'length' in each and int(each['length'], 0) == 0:
+ continue
+
+ if 'include' in each:
+ if each['include']:
+ each['include'] = self.normalize_file_name(each['include'])
+ file_lines[file].extend(['', '- !include %s' % each['include'], ''])
+ file = each['include']
+ else:
+ file = '.'
+ continue
+
+ if file not in file_lines:
+ file_lines[file] = []
+
+ lines = file_lines[file]
+ name = each['cname']
+
+ prefix = name[0]
+ if prefix == '<':
+ level += 1
+
+ padding = ' ' * level
+ if prefix not in '<>@':
+ padding += ' '
+ else:
+ name = name[1:]
+ if prefix == '@':
+ padding += ' '
+
+ if ':' in name:
+ parts = name.split(':')
+ name = parts[0]
+
+ padding = padding[2:] if is_configs else padding
+
+ if prefix != '>':
+ if 'expand' in each:
+ lines.append('%s- %s' % (padding, each['expand']))
+ else:
+ lines.append('%s- %-12s :' % (padding, name))
+
+ for field in each:
+ if field in ['cname', 'expand', 'include']:
+ continue
+ value_str = self.format_value(field, each[field], padding + ' ' * 16)
+ full_line = ' %s %-12s : %s' % (padding, field, value_str)
+ lines.extend(full_line.splitlines())
+
+ if prefix == '>':
+ level -= 1
+ if level == 0:
+ lines.append('')
+
+ return file_lines
+
+
+def bsf_to_dsc(bsf_file, dsc_file):
+ fsp_dsc = CFspBsf2Dsc(bsf_file)
+ dsc_lines = fsp_dsc.get_dsc_lines()
+ fd = open(dsc_file, 'w')
+ fd.write('\n'.join(dsc_lines))
+ fd.close()
+ return
+
+
+def dsc_to_yaml(dsc_file, yaml_file):
+ dsc2yaml = CFspDsc2Yaml()
+ dsc2yaml.load_config_data_from_dsc(dsc_file)
+
+ cfgs = {}
+ for cfg in ['Template', 'Option']:
+ if cfg == 'Template':
+ file_lines = dsc2yaml.output_template()
+ else:
+ file_lines = dsc2yaml.output_config()
+ for file in file_lines:
+ lines = file_lines[file]
+ if file == '.':
+ cfgs[cfg] = lines
+ else:
+ if('/' in file or '\\' in file):
+ continue
+ file = os.path.basename(file)
+ fo = open(os.path.join(file), 'w')
+ fo.write(__copyright_tmp__ % (cfg, date.today().year) + '\n\n')
+ for line in lines:
+ fo.write(line + '\n')
+ fo.close()
+
+ variables = dsc2yaml.output_variable()
+ fo = open(yaml_file, 'w')
+ fo.write(__copyright_tmp__ % ('Default', date.today().year))
+ if len(variables) > 0:
+ fo.write('\n\nvariable:\n')
+ for line in variables:
+ fo.write(' ' + line + '\n')
+
+ fo.write('\n\ntemplate:\n')
+ for line in cfgs['Template']:
+ if line != '':
+ fo.write(' ' + line + '\n')
+
+ fo.write('\n\nconfigs:\n')
+ for line in cfgs['Option']:
+ if line != '':
+ fo.write(' ' + line + '\n')
+
+ fo.close()
+
+
+def get_fsp_name_from_path(bsf_file):
+ name = ''
+ parts = bsf_file.split(os.sep)
+ for part in parts:
+ if part.endswith('FspBinPkg'):
+ name = part[:-9]
+ break
+ if not name:
+ raise Exception('Could not get FSP name from file path!')
+ return name
+
+
+def usage():
+ print('\n'.join([
+ "FspDscBsf2Yaml Version 0.10",
+ "Usage:",
+ " FspDscBsf2Yaml BsfFile|DscFile YamlFile"
+ ]))
+
+
+def main():
+ #
+ # Parse the options and args
+ #
+ argc = len(sys.argv)
+ if argc < 3:
+ usage()
+ return 1
+
+ bsf_file = sys.argv[1]
+ yaml_file = sys.argv[2]
+ if os.path.isdir(yaml_file):
+ yaml_file = os.path.join(yaml_file, get_fsp_name_from_path(bsf_file) + '.yaml')
+
+ if bsf_file.endswith('.dsc'):
+ dsc_file = bsf_file
+ bsf_file = ''
+ else:
+ dsc_file = os.path.splitext(yaml_file)[0] + '.dsc'
+ bsf_to_dsc(bsf_file, dsc_file)
+
+ dsc_to_yaml(dsc_file, yaml_file)
+
+ print("'%s' was created successfully!" % yaml_file)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/GenCfgOpt.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/GenCfgOpt.py
new file mode 100755
index 00000000..34484c16
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/GenCfgOpt.py
@@ -0,0 +1,1791 @@
+## @ GenCfgOpt.py
+#
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+import os
+import re
+import sys
+import struct
+from datetime import date
+from functools import reduce
+
+# Generated file copyright header
+
+__copyright_txt__ = """## @file
+#
+# THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION.
+#
+# This file lists all VPD informations for a platform collected by build.exe.
+#
+# Copyright (c) %4d, 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.
+#
+"""
+
+__copyright_bsf__ = """/** @file
+
+ Boot Setting File for Platform Configuration.
+
+ Copyright (c) %4d, 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.
+
+ This file is automatically generated. Please do NOT modify !!!
+
+**/
+
+"""
+
+__copyright_h__ = """/** @file
+
+Copyright (c) %4d, Intel Corporation. All rights reserved.<BR>
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this
+ list of conditions and the following disclaimer in the documentation and/or
+ other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+
+ This file is automatically generated. Please do NOT modify !!!
+
+**/
+"""
+
+BuildOptionPcd = []
+
+class CLogicalExpression:
+ def __init__(self):
+ self.index = 0
+ self.string = ''
+
+ def errExit(self, err = ''):
+ print ("ERROR: Express parsing for:")
+ print (" %s" % self.string)
+ print (" %s^" % (' ' * self.index))
+ if err:
+ print ("INFO : %s" % err)
+ raise SystemExit
+
+ def getNonNumber (self, n1, n2):
+ if not n1.isdigit():
+ return n1
+ if not n2.isdigit():
+ return n2
+ return None
+
+ def getCurr(self, lens = 1):
+ try:
+ if lens == -1:
+ return self.string[self.index :]
+ else:
+ if self.index + lens > len(self.string):
+ lens = len(self.string) - self.index
+ return self.string[self.index : self.index + lens]
+ except Exception:
+ return ''
+
+ def isLast(self):
+ return self.index == len(self.string)
+
+ def moveNext(self, len = 1):
+ self.index += len
+
+ def skipSpace(self):
+ while not self.isLast():
+ if self.getCurr() in ' \t':
+ self.moveNext()
+ else:
+ return
+
+ def normNumber (self, val):
+ return True if val else False
+
+ def getNumber(self, var):
+ var = var.strip()
+ if re.match('^0x[a-fA-F0-9]+$', var):
+ value = int(var, 16)
+ elif re.match('^[+-]?\d+$', var):
+ value = int(var, 10)
+ else:
+ value = None
+ return value
+
+ def parseValue(self):
+ self.skipSpace()
+ var = ''
+ while not self.isLast():
+ char = self.getCurr()
+ if re.match('^[\w.]', char):
+ var += char
+ self.moveNext()
+ else:
+ break
+ val = self.getNumber(var)
+ if val is None:
+ value = var
+ else:
+ value = "%d" % val
+ return value
+
+ def parseSingleOp(self):
+ self.skipSpace()
+ if re.match('^NOT\W', self.getCurr(-1)):
+ self.moveNext(3)
+ op = self.parseBrace()
+ val = self.getNumber (op)
+ if val is None:
+ self.errExit ("'%s' is not a number" % op)
+ return "%d" % (not self.normNumber(int(op)))
+ else:
+ return self.parseValue()
+
+ def parseBrace(self):
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '(':
+ self.moveNext()
+ value = self.parseExpr()
+ self.skipSpace()
+ if self.getCurr() != ')':
+ self.errExit ("Expecting closing brace or operator")
+ self.moveNext()
+ return value
+ else:
+ value = self.parseSingleOp()
+ return value
+
+ def parseCompare(self):
+ value = self.parseBrace()
+ while True:
+ self.skipSpace()
+ char = self.getCurr()
+ if char in ['<', '>']:
+ self.moveNext()
+ next = self.getCurr()
+ if next == '=':
+ op = char + next
+ self.moveNext()
+ else:
+ op = char
+ result = self.parseBrace()
+ test = self.getNonNumber(result, value)
+ if test is None:
+ value = "%d" % self.normNumber(eval (value + op + result))
+ else:
+ self.errExit ("'%s' is not a valid number for comparision" % test)
+ elif char in ['=', '!']:
+ op = self.getCurr(2)
+ if op in ['==', '!=']:
+ self.moveNext(2)
+ result = self.parseBrace()
+ test = self.getNonNumber(result, value)
+ if test is None:
+ value = "%d" % self.normNumber((eval (value + op + result)))
+ else:
+ value = "%d" % self.normNumber(eval ("'" + value + "'" + op + "'" + result + "'"))
+ else:
+ break
+ else:
+ break
+ return value
+
+ def parseAnd(self):
+ value = self.parseCompare()
+ while True:
+ self.skipSpace()
+ if re.match('^AND\W', self.getCurr(-1)):
+ self.moveNext(3)
+ result = self.parseCompare()
+ test = self.getNonNumber(result, value)
+ if test is None:
+ value = "%d" % self.normNumber(int(value) & int(result))
+ else:
+ self.errExit ("'%s' is not a valid op number for AND" % test)
+ else:
+ break
+ return value
+
+ def parseOrXor(self):
+ value = self.parseAnd()
+ op = None
+ while True:
+ self.skipSpace()
+ op = None
+ if re.match('^XOR\W', self.getCurr(-1)):
+ self.moveNext(3)
+ op = '^'
+ elif re.match('^OR\W', self.getCurr(-1)):
+ self.moveNext(2)
+ op = '|'
+ else:
+ break
+ if op:
+ result = self.parseAnd()
+ test = self.getNonNumber(result, value)
+ if test is None:
+ value = "%d" % self.normNumber(eval (value + op + result))
+ else:
+ self.errExit ("'%s' is not a valid op number for XOR/OR" % test)
+ return value
+
+ def parseExpr(self):
+ return self.parseOrXor()
+
+ def getResult(self):
+ value = self.parseExpr()
+ self.skipSpace()
+ if not self.isLast():
+ self.errExit ("Unexpected character found '%s'" % self.getCurr())
+ test = self.getNumber(value)
+ if test is None:
+ self.errExit ("Result '%s' is not a number" % value)
+ return int(value)
+
+ def evaluateExpress (self, Expr):
+ self.index = 0
+ self.string = Expr
+ if self.getResult():
+ Result = True
+ else:
+ Result = False
+ return Result
+
+class CGenCfgOpt:
+ def __init__(self, Mode = ''):
+ self.Debug = False
+ self.Error = ''
+ self.Mode = Mode
+ self._GlobalDataDef = """
+GlobalDataDef
+ SKUID = 0, "DEFAULT"
+EndGlobalData
+
+"""
+ self._BuidinOptionTxt = """
+List &EN_DIS
+ Selection 0x1 , "Enabled"
+ Selection 0x0 , "Disabled"
+EndList
+
+"""
+ self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE', 'PAGES', 'BLOCK', 'OPTION','CONDITION','ORDER', 'MARKER', 'SUBT']
+ self._HdrKeyList = ['HEADER','STRUCT', 'EMBED', 'COMMENT']
+ self._BuidinOption = {'$EN_DIS' : 'EN_DIS'}
+
+ self._MacroDict = {}
+ self._VarDict = {}
+ self._PcdsDict = {}
+ self._CfgBlkDict = {}
+ self._CfgPageDict = {}
+ self._BsfTempDict = {}
+ self._CfgItemList = []
+ self._DscLines = []
+ self._DscFile = ''
+
+ self._MapVer = 0
+ self._DscTime = 0
+
+ def ParseMacros (self, MacroDefStr):
+ # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
+ self._MacroDict = {}
+ IsExpression = False
+ for Macro in MacroDefStr:
+ if Macro.startswith('-D'):
+ IsExpression = True
+ if len(Macro) > 2:
+ Macro = Macro[2:]
+ else :
+ continue
+ if IsExpression:
+ IsExpression = False
+ Match = re.match("(\w+)=(.+)", Macro)
+ if Match:
+ self._MacroDict[Match.group(1)] = Match.group(2)
+ else:
+ Match = re.match("(\w+)", Macro)
+ if Match:
+ self._MacroDict[Match.group(1)] = ''
+ if len(self._MacroDict) == 0:
+ Error = 1
+ else:
+ Error = 0
+ if self.Debug:
+ print ("INFO : Macro dictionary:")
+ for Each in self._MacroDict:
+ print (" $(%s) = [ %s ]" % (Each , self._MacroDict[Each]))
+ return Error
+
+ def EvaulateIfdef (self, Macro):
+ Result = Macro in self._MacroDict
+ if self.Debug:
+ print ("INFO : Eval Ifdef [%s] : %s" % (Macro, Result))
+ return Result
+
+ def ExpandMacros (self, Input, Preserve = False):
+ Line = Input
+ Match = re.findall("\$\(\w+\)", Input)
+ if Match:
+ for Each in Match:
+ Variable = Each[2:-1]
+ if Variable in self._MacroDict:
+ Line = Line.replace(Each, self._MacroDict[Variable])
+ else:
+ if self.Debug:
+ print ("WARN : %s is not defined" % Each)
+ if not Preserve:
+ Line = Line.replace(Each, Each[2:-1])
+ return Line
+
+ def ExpandPcds (self, Input):
+ Line = Input
+ Match = re.findall("(\w+\.\w+)", Input)
+ if Match:
+ for PcdName in Match:
+ if PcdName in self._PcdsDict:
+ Line = Line.replace(PcdName, self._PcdsDict[PcdName])
+ else:
+ if self.Debug:
+ print ("WARN : %s is not defined" % PcdName)
+ return Line
+
+ def EvaluateExpress (self, Expr):
+ ExpExpr = self.ExpandPcds(Expr)
+ ExpExpr = self.ExpandMacros(ExpExpr)
+ LogExpr = CLogicalExpression()
+ Result = LogExpr.evaluateExpress (ExpExpr)
+ if self.Debug:
+ print ("INFO : Eval Express [%s] : %s" % (Expr, Result))
+ return Result
+
+ def ValueToByteArray (self, ValueStr, Length):
+ Match = re.match("\{\s*FILE:(.+)\}", ValueStr)
+ if Match:
+ FileList = Match.group(1).split(',')
+ Result = bytearray()
+ for File in FileList:
+ File = File.strip()
+ BinPath = os.path.join(os.path.dirname(self._DscFile), File)
+ Result.extend(bytearray(open(BinPath, 'rb').read()))
+ else:
+ try:
+ Result = bytearray(self.ValueToList(ValueStr, Length))
+ except ValueError as e:
+ raise Exception ("Bytes in '%s' must be in range 0~255 !" % ValueStr)
+ if len(Result) < Length:
+ Result.extend(b'\x00' * (Length - len(Result)))
+ elif len(Result) > Length:
+ raise Exception ("Value '%s' is too big to fit into %d bytes !" % (ValueStr, Length))
+
+ return Result[:Length]
+
+ def ValueToList (self, ValueStr, Length):
+ if ValueStr[0] == '{':
+ Result = []
+ BinList = ValueStr[1:-1].split(',')
+ InBitField = False
+ LastInBitField = False
+ Value = 0
+ BitLen = 0
+ for Element in BinList:
+ InBitField = False
+ Each = Element.strip()
+ if len(Each) == 0:
+ pass
+ else:
+ if Each[0] in ['"', "'"]:
+ Result.extend(list(bytearray(Each[1:-1], 'utf-8')))
+ elif ':' in Each:
+ Match = re.match("(.+):(\d+)b", Each)
+ if Match is None:
+ raise Exception("Invald value list format '%s' !" % Each)
+ InBitField = True
+ CurrentBitLen = int(Match.group(2))
+ CurrentValue = ((self.EvaluateExpress(Match.group(1)) & (1<<CurrentBitLen) - 1)) << BitLen
+ else:
+ Result.append(self.EvaluateExpress(Each.strip()))
+ if InBitField:
+ Value += CurrentValue
+ BitLen += CurrentBitLen
+ if LastInBitField and ((not InBitField) or (Element == BinList[-1])):
+ if BitLen % 8 != 0:
+ raise Exception("Invald bit field length!")
+ Result.extend(Val2Bytes(Value, BitLen // 8))
+ Value = 0
+ BitLen = 0
+ LastInBitField = InBitField
+ elif ValueStr.startswith("'") and ValueStr.endswith("'"):
+ Result = Str2Bytes (ValueStr, Length)
+ elif ValueStr.startswith('"') and ValueStr.endswith('"'):
+ Result = Str2Bytes (ValueStr, Length)
+ else:
+ Result = Val2Bytes (self.EvaluateExpress(ValueStr), Length)
+ return Result
+
+ def FormatListValue(self, ConfigDict):
+ Struct = ConfigDict['struct']
+ if Struct not in ['UINT8','UINT16','UINT32','UINT64']:
+ return
+
+ dataarray = []
+ binlist = ConfigDict['value'][1:-1].split(',')
+ for each in binlist:
+ each = each.strip()
+ if each.startswith('0x'):
+ value = int(each, 16)
+ else:
+ value = int(each)
+ dataarray.append(value)
+
+ unit = int(Struct[4:]) / 8
+ if int(ConfigDict['length']) != unit * len(dataarray):
+ raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname'])
+
+ bytearray = []
+ for each in dataarray:
+ value = each
+ for loop in range(int(unit)):
+ bytearray.append("0x%02X" % (value & 0xFF))
+ value = value >> 8
+ newvalue = '{' + ','.join(bytearray) + '}'
+ ConfigDict['value'] = newvalue
+ return ""
+
+ def ParseDscFile (self, DscFile, FvDir):
+ Hardcode = False
+ AutoAlign = False
+ self._CfgItemList = []
+ self._CfgPageDict = {}
+ self._CfgBlkDict = {}
+ self._DscFile = DscFile
+ self._FvDir = FvDir
+
+ self._DscLines = []
+ self._BsfTempDict = {}
+
+ # Initial DSC time is parent DSC time.
+ self._DscTime = os.path.getmtime(DscFile)
+
+ CfgDict = {}
+
+ IsDefSect = False
+ IsPcdSect = False
+ IsUpdSect = False
+ IsVpdSect = False
+ IsTmpSect = False
+
+ TemplateName = ''
+
+ IfStack = []
+ ElifStack = []
+ Error = 0
+ ConfigDict = {}
+
+
+ if type(DscFile) is list:
+ # it is DSC lines already
+ DscLines = DscFile
+ self._DscFile = '.'
+ else:
+ DscFd = open(DscFile, "r")
+ DscLines = DscFd.readlines()
+ DscFd.close()
+ self._DscFile = DscFile
+
+ SkipLines = 0
+
+ MaxAlign = 32 #Default align to 32, but if there are 64 bit unit, align to 64
+ SizeAlign = 0 #record the struct max align
+ Base = 0 #Starting offset of sub-structure.
+
+ while len(DscLines):
+ DscLine = DscLines.pop(0).strip()
+ if SkipLines == 0:
+ self._DscLines.append (DscLine)
+ else:
+ SkipLines = SkipLines - 1
+ if len(DscLine) == 0:
+ continue
+
+ Handle = False
+ Match = re.match("^\[(.+)\]", DscLine)
+ if Match is not None:
+ IsDefSect = False
+ IsPcdSect = False
+ IsVpdSect = False
+ IsUpdSect = False
+ IsTmpSect = False
+ SectionName = Match.group(1).lower()
+ if SectionName == "Defines".lower():
+ IsDefSect = True
+ if (SectionName == "PcdsFeatureFlag".lower() or SectionName == "PcdsFixedAtBuild".lower()):
+ IsPcdSect = True
+ elif SectionName == "PcdsDynamicVpd.Tmp".lower():
+ IsTmpSect = True
+ elif SectionName == "PcdsDynamicVpd.Upd".lower():
+ ConfigDict = {}
+ ConfigDict['header'] = 'ON'
+ ConfigDict['region'] = 'UPD'
+ ConfigDict['order'] = -1
+ ConfigDict['page'] = ''
+ ConfigDict['name'] = ''
+ ConfigDict['find'] = ''
+ ConfigDict['marker'] = ''
+ ConfigDict['struct'] = ''
+ ConfigDict['embed'] = ''
+ ConfigDict['comment'] = ''
+ ConfigDict['subreg'] = []
+ ConfigDict['condition'] = ''
+ ConfigDict['option'] = ''
+ IsUpdSect = True
+ Offset = 0
+ else:
+ if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect or IsTmpSect:
+
+ Match = False if DscLine[0] != '!' else True
+ if Match:
+ Match = re.match("^!(else|endif|ifdef|ifndef|if|elseif|include)\s*(.+)?$", DscLine.split("#")[0])
+ Keyword = Match.group(1) if Match else ''
+ Remaining = Match.group(2) if Match else ''
+ Remaining = '' if Remaining is None else Remaining.strip()
+
+ if Keyword in ['if', 'elseif', 'ifdef', 'ifndef', 'include'] and not Remaining:
+ raise Exception ("ERROR: Expression is expected after '!if' or !elseif' for line '%s'" % DscLine)
+
+ if Keyword == 'else':
+ if IfStack:
+ IfStack[-1] = not IfStack[-1]
+ else:
+ raise Exception ("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)
+ elif Keyword == 'endif':
+ if IfStack:
+ IfStack.pop()
+ Level = ElifStack.pop()
+ if Level > 0:
+ del IfStack[-Level:]
+ else:
+ raise Exception ("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)
+ elif Keyword == 'ifdef' or Keyword == 'ifndef':
+ Result = self.EvaulateIfdef (Remaining)
+ if Keyword == 'ifndef':
+ Result = not Result
+ IfStack.append(Result)
+ ElifStack.append(0)
+ elif Keyword == 'if' or Keyword == 'elseif':
+ Result = self.EvaluateExpress(Remaining)
+ if Keyword == "if":
+ ElifStack.append(0)
+ IfStack.append(Result)
+ else: #elseif
+ if IfStack:
+ IfStack[-1] = not IfStack[-1]
+ IfStack.append(Result)
+ ElifStack[-1] = ElifStack[-1] + 1
+ else:
+ raise Exception ("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)
+ else:
+ if IfStack:
+ Handle = reduce(lambda x,y: x and y, IfStack)
+ else:
+ Handle = True
+ if Handle:
+ Match = re.match("!include\s+(.+)", DscLine)
+ if Match:
+ IncludeFilePath = Match.group(1)
+ IncludeFilePath = self.ExpandMacros(IncludeFilePath)
+ PackagesPath = os.getenv("PACKAGES_PATH")
+ if PackagesPath:
+ for PackagePath in PackagesPath.split(os.pathsep):
+ IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))
+ if os.path.exists(IncludeFilePathAbs):
+ IncludeDsc = open(IncludeFilePathAbs, "r")
+ break
+ else:
+ IncludeDsc = open(IncludeFilePath, "r")
+ if IncludeDsc == None:
+ print("ERROR: Cannot open file '%s'" % IncludeFilePath)
+ raise SystemExit
+
+ # Update DscTime when newer DSC time found.
+ CurrentDscTime = os.path.getmtime(os.path.realpath(IncludeDsc.name))
+ if CurrentDscTime > self._DscTime:
+ self._DscTime = CurrentDscTime
+
+ NewDscLines = IncludeDsc.readlines()
+ IncludeDsc.close()
+ DscLines = NewDscLines + DscLines
+ del self._DscLines[-1]
+ Offset = 0
+ else:
+ if DscLine.startswith('!'):
+ print("ERROR: Unrecognized directive for line '%s'" % DscLine)
+ raise SystemExit
+ if not Handle:
+ del self._DscLines[-1]
+ continue
+
+ if IsDefSect:
+ #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09
+ #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
+ #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
+ #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
+ Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*(.+)", DscLine)
+ if Match:
+ self._MacroDict[Match.group(1)] = self.ExpandMacros(Match.group(2))
+ if self.Debug:
+ print ("INFO : DEFINE %s = [ %s ]" % (Match.group(1), self.ExpandMacros(Match.group(2))))
+ elif IsPcdSect:
+ #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE
+ #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE
+ Match = re.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine)
+ if Match:
+ self._PcdsDict[Match.group(1)] = Match.group(2)
+ if self.Debug:
+ print ("INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2)))
+ i = 0
+ while i < len(BuildOptionPcd):
+ Match = re.match("\s*([\w\.]+)\s*\=\s*(\w+)", BuildOptionPcd[i])
+ if Match:
+ self._PcdsDict[Match.group(1)] = Match.group(2)
+ i += 1
+
+ elif IsTmpSect:
+ # !BSF DEFT:{GPIO_TMPL:START}
+ Match = re.match("^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", DscLine)
+ if Match:
+ if Match.group(3) == 'START' and not TemplateName:
+ TemplateName = Match.group(2).strip()
+ self._BsfTempDict[TemplateName] = []
+ if Match.group(3) == 'END' and (TemplateName == Match.group(2).strip()) and TemplateName:
+ TemplateName = ''
+ else:
+ if TemplateName:
+ Match = re.match("^!include\s*(.+)?$", DscLine)
+ if Match:
+ continue
+ self._BsfTempDict[TemplateName].append(DscLine)
+
+ else:
+ Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)
+ if Match:
+ Remaining = Match.group(2)
+ if Match.group(1) == '!BSF' or Match.group(1) == '@Bsf':
+ Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining)
+ if Match:
+ # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"}
+ PageList = Match.group(1).split(',')
+ for Page in PageList:
+ Page = Page.strip()
+ Match = re.match("(\w+):\"(.+)\"", Page)
+ if Match != None:
+ self._CfgPageDict[Match.group(1)] = Match.group(2)
+
+ Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)
+ if Match:
+ self._CfgBlkDict['name'] = Match.group(1)
+ self._CfgBlkDict['ver'] = Match.group(2)
+
+ for Key in self._BsfKeyList:
+ Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
+ if Match:
+ if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'):
+ ConfigDict[Key.lower()] += Match.group(1)[1:]
+ else:
+ ConfigDict[Key.lower()] = Match.group(1)
+ else:
+ for Key in self._HdrKeyList:
+ Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining)
+ if Match:
+ ConfigDict[Key.lower()] = Match.group(1)
+
+ Match = re.match("^\s*#\s+@Prompt\s+(.+)", DscLine)
+ if Match:
+ ConfigDict['name'] = Match.group(1)
+
+ Match = re.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine)
+ if Match:
+ if Match.group(2).strip() in self._BuidinOption:
+ ConfigDict['option'] = Match.group(2).strip()
+ else:
+ OptionValueList = Match.group(2).split(',')
+ OptionStringList = Match.group(3).split(',')
+ Index = 0
+ for Option in OptionValueList:
+ Option = Option.strip()
+ ConfigDict['option'] = ConfigDict['option'] + str(Option) + ':' + OptionStringList[Index].strip()
+ Index += 1
+ if Index in range(len(OptionValueList)):
+ ConfigDict['option'] += ', '
+ ConfigDict['type'] = "Combo"
+
+ Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)
+ if Match:
+ if "0x" in Match.group(2) or "0x" in Match.group(3):
+ ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))
+ else:
+ ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))
+
+ Match = re.match("^\s*##\s+(.+)", DscLine)
+ if Match:
+ ConfigDict['help'] = Match.group(1)
+
+ # Check VPD/UPD
+ if IsUpdSect:
+ Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+|\*)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine)
+ else:
+ Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine)
+ if Match:
+ ConfigDict['space'] = Match.group(1)
+ ConfigDict['cname'] = Match.group(2)
+ if Match.group(3) != '*':
+ Hardcode = True
+ Offset = int (Match.group(3), 16)
+ else:
+ AutoAlign = True
+
+ if Hardcode and AutoAlign:
+ print("Hardcode and auto-align mixed mode is not supported by GenCfgOpt")
+ raise SystemExit
+ ConfigDict['offset'] = Offset
+ if ConfigDict['order'] == -1:
+ ConfigDict['order'] = ConfigDict['offset'] << 8
+ else:
+ (Major, Minor) = ConfigDict['order'].split('.')
+ ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16)
+ if IsUpdSect:
+ Value = Match.group(5).strip()
+ if Match.group(4).startswith("0x"):
+ Length = int (Match.group(4), 16)
+ else :
+ Length = int (Match.group(4))
+ Offset += Length
+ else:
+ Value = Match.group(4)
+ if Value is None:
+ Value = ''
+ Value = Value.strip()
+ if '|' in Value:
+ Match = re.match("^.+\s*\|\s*(.+)", Value)
+ if Match:
+ Value = Match.group(1)
+ Length = -1
+
+ ConfigDict['length'] = Length
+ Match = re.match("\$\((\w+)\)", Value)
+ if Match:
+ if Match.group(1) in self._MacroDict:
+ Value = self._MacroDict[Match.group(1)]
+
+ ConfigDict['value'] = Value
+ if (len(Value) > 0) and (Value[0] == '{'):
+ Value = self.FormatListValue(ConfigDict)
+
+ if ConfigDict['name'] == '':
+ # Clear BSF specific items
+ ConfigDict['bsfname'] = ''
+ ConfigDict['help'] = ''
+ ConfigDict['type'] = ''
+ ConfigDict['option'] = ''
+ if IsUpdSect and AutoAlign:
+ ItemLength = int(ConfigDict['length'])
+ ItemOffset = int(ConfigDict['offset'])
+ ItemStruct = ConfigDict['struct']
+ Unit = 1
+ if ItemLength in [1, 2, 4, 8] and not ConfigDict['value'].startswith('{'):
+ Unit = ItemLength
+ # If there are 64 bit unit, align to 64
+ if Unit == 8:
+ MaxAlign = 64
+ SizeAlign = 8
+ if ItemStruct != '':
+ UnitDict = {'UINT8':1, 'UINT16':2, 'UINT32':4, 'UINT64':8}
+ if ItemStruct in ['UINT8', 'UINT16', 'UINT32', 'UINT64']:
+ Unit = UnitDict[ItemStruct]
+ # If there are 64 bit unit, align to 64
+ if Unit == 8:
+ MaxAlign = 64
+ SizeAlign = max(SizeAlign, Unit)
+ if (ConfigDict['embed'].find(':START') != -1):
+ Base = ItemOffset
+ SubOffset = ItemOffset - Base
+ SubRemainder = SubOffset % Unit
+ if SubRemainder:
+ Diff = Unit - SubRemainder
+ Offset = Offset + Diff
+ ItemOffset = ItemOffset + Diff
+
+ if (ConfigDict['embed'].find(':END') != -1):
+ Remainder = Offset % (MaxAlign/8) # MaxAlign is either 32 or 64
+ if Remainder:
+ Diff = int((MaxAlign/8) - Remainder)
+ Offset = Offset + Diff
+ ItemOffset = ItemOffset + Diff
+ MaxAlign = 32 # Reset to default 32 align when struct end
+ if (ConfigDict['cname'] == 'UpdTerminator'):
+ # ItemLength is the size of UpdTerminator
+ # Itemlength might be 16, 32, or 64
+ # Struct align to 64 if UpdTerminator
+ # or struct size is 64 bit, else align to 32
+ Remainder = Offset % max(ItemLength/8, 4, SizeAlign)
+ Offset = Offset + ItemLength
+ if Remainder:
+ Diff = int(max(ItemLength/8, 4, SizeAlign) - Remainder)
+ ItemOffset = ItemOffset + Diff
+ ConfigDict['offset'] = ItemOffset
+
+ self._CfgItemList.append(ConfigDict.copy())
+ ConfigDict['name'] = ''
+ ConfigDict['find'] = ''
+ ConfigDict['struct'] = ''
+ ConfigDict['embed'] = ''
+ ConfigDict['comment'] = ''
+ ConfigDict['marker'] = ''
+ ConfigDict['order'] = -1
+ ConfigDict['subreg'] = []
+ ConfigDict['option'] = ''
+ else:
+ # It could be a virtual item as below
+ # !BSF FIELD:{SerialDebugPortAddress0:1}
+ # or
+ # @Bsf FIELD:{SerialDebugPortAddress0:1b}
+ Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine)
+ if Match:
+ SubCfgDict = ConfigDict.copy()
+ if (Match.group(4) == None) or (Match.group(4) == 'B'):
+ UnitBitLen = 8
+ elif Match.group(4) == 'b':
+ UnitBitLen = 1
+ else:
+ print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine)
+ raise SystemExit
+ SubCfgDict['cname'] = Match.group(2)
+ SubCfgDict['bitlength'] = int (Match.group(3)) * UnitBitLen
+ if SubCfgDict['bitlength'] > 0:
+ LastItem = self._CfgItemList[-1]
+ if len(LastItem['subreg']) == 0:
+ SubOffset = 0
+ else:
+ SubOffset = LastItem['subreg'][-1]['bitoffset'] + LastItem['subreg'][-1]['bitlength']
+ SubCfgDict['bitoffset'] = SubOffset
+ LastItem['subreg'].append (SubCfgDict.copy())
+ ConfigDict['name'] = ''
+ return Error
+
+ def GetBsfBitFields (self, subitem, bytes):
+ start = subitem['bitoffset']
+ end = start + subitem['bitlength']
+ bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1])
+ bitsvalue = bitsvalue[::-1]
+ bitslen = len(bitsvalue)
+ if start > bitslen or end > bitslen:
+ raise Exception ("Invalid bits offset [%d,%d] %d for %s" % (start, end, bitslen, subitem['name']))
+ return '0x%X' % (int(bitsvalue[start:end][::-1], 2))
+
+ def UpdateSubRegionDefaultValue (self):
+ Error = 0
+ for Item in self._CfgItemList:
+ if len(Item['subreg']) == 0:
+ continue
+ bytearray = []
+ if Item['value'][0] == '{':
+ binlist = Item['value'][1:-1].split(',')
+ for each in binlist:
+ each = each.strip()
+ if each.startswith('0x'):
+ value = int(each, 16)
+ else:
+ value = int(each)
+ bytearray.append(value)
+ else:
+ if Item['value'].startswith('0x'):
+ value = int(Item['value'], 16)
+ else:
+ value = int(Item['value'])
+ idx = 0
+ while idx < Item['length']:
+ bytearray.append(value & 0xFF)
+ value = value >> 8
+ idx = idx + 1
+ for SubItem in Item['subreg']:
+ valuestr = self.GetBsfBitFields(SubItem, bytearray)
+ SubItem['value'] = valuestr
+ return Error
+
+ def NoDscFileChange (self, OutPutFile):
+ NoFileChange = True
+ if not os.path.exists(OutPutFile):
+ NoFileChange = False
+ else:
+ OutputTime = os.path.getmtime(OutPutFile)
+ if self._DscTime > OutputTime:
+ NoFileChange = False
+ return NoFileChange
+
+ def CreateSplitUpdTxt (self, UpdTxtFile):
+ GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']
+ SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS
+ for Index in range(len(GuidList)):
+ UpdTxtFile = ''
+ FvDir = self._FvDir
+ if GuidList[Index] not in self._MacroDict:
+ self.Error = "%s definition is missing in DSC file" % (GuidList[Index])
+ return 1
+
+ if UpdTxtFile == '':
+ UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')
+
+ if (self.NoDscFileChange (UpdTxtFile)):
+ # DSC has not been modified yet
+ # So don't have to re-generate other files
+ self.Error = 'No DSC file change, skip to create UPD TXT file'
+ return 256
+
+ TxtFd = open(UpdTxtFile, "w")
+ TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year))
+
+ NextOffset = 0
+ SpaceIdx = 0
+ StartAddr = 0
+ EndAddr = 0
+ Default = 'DEFAULT|'
+ InRange = False
+ for Item in self._CfgItemList:
+ if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:
+ StartAddr = Item['offset']
+ NextOffset = StartAddr
+ InRange = True
+ if Item['cname'] == 'UpdTerminator' and InRange == True:
+ EndAddr = Item['offset']
+ InRange = False
+ InRange = False
+ for Item in self._CfgItemList:
+ if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]:
+ InRange = True
+ if InRange != True:
+ continue
+ if Item['cname'] == 'UpdTerminator':
+ InRange = False
+ if Item['region'] != 'UPD':
+ continue
+ Offset = Item['offset']
+ if StartAddr > Offset or EndAddr < Offset:
+ continue
+ if NextOffset < Offset:
+ # insert one line
+ TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset))
+ SpaceIdx = SpaceIdx + 1
+ NextOffset = Offset + Item['length']
+ TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value']))
+ TxtFd.close()
+ return 0
+
+ def CreateVarDict (self):
+ Error = 0
+ self._VarDict = {}
+ if len(self._CfgItemList) > 0:
+ Item = self._CfgItemList[-1]
+ self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] + Item['length'])
+ for Item in self._CfgItemList:
+ Embed = Item['embed']
+ Match = re.match("^(\w+):(\w+):(START|END)", Embed)
+ if Match:
+ StructName = Match.group(1)
+ VarName = '_%s_%s_' % (Match.group(3), StructName)
+ if Match.group(3) == 'END':
+ self._VarDict[VarName] = Item['offset'] + Item['length']
+ self._VarDict['_LENGTH_%s_' % StructName] = \
+ self._VarDict['_END_%s_' % StructName] - self._VarDict['_START_%s_' % StructName]
+ if Match.group(2).startswith('TAG_'):
+ if (self.Mode != 'FSP') and (self._VarDict['_LENGTH_%s_' % StructName] % 4):
+ raise Exception("Size of structure '%s' is %d, not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName]))
+ self._VarDict['_TAG_%s_' % StructName] = int (Match.group(2)[4:], 16) & 0xFFF
+ else:
+ self._VarDict[VarName] = Item['offset']
+ if Item['marker']:
+ self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = Item['offset']
+ return Error
+
+ def UpdateBsfBitUnit (self, Item):
+ BitTotal = 0
+ BitOffset = 0
+ StartIdx = 0
+ Unit = None
+ UnitDec = {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'}
+ for Idx, SubItem in enumerate(Item['subreg']):
+ if Unit is None:
+ Unit = SubItem['bitunit']
+ BitLength = SubItem['bitlength']
+ BitTotal += BitLength
+ BitOffset += BitLength
+
+ if BitOffset > 64 or BitOffset > Unit * 8:
+ break
+
+ if BitOffset == Unit * 8:
+ for SubIdx in range (StartIdx, Idx + 1):
+ Item['subreg'][SubIdx]['bitunit'] = Unit
+ BitOffset = 0
+ StartIdx = Idx + 1
+ Unit = None
+
+ if BitOffset > 0:
+ raise Exception ("Bit fields cannot fit into %s for '%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname']))
+
+ ExpectedTotal = Item['length'] * 8
+ if Item['length'] * 8 != BitTotal:
+ raise Exception ("Bit fields total length (%d) does not match length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname']))
+
+ def UpdateDefaultValue (self):
+ Error = 0
+ for Idx, Item in enumerate(self._CfgItemList):
+ if len(Item['subreg']) == 0:
+ Value = Item['value']
+ if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or Value[0] == '"'):
+ # {XXX} or 'XXX' strings
+ self.FormatListValue(self._CfgItemList[Idx])
+ else:
+ Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value)
+ if not Match:
+ NumValue = self.EvaluateExpress (Value)
+ Item['value'] = '0x%X' % NumValue
+ else:
+ ValArray = self.ValueToByteArray (Item['value'], Item['length'])
+ for SubItem in Item['subreg']:
+ SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray)
+ self.UpdateBsfBitUnit (Item)
+ return Error
+
+ def ProcessMultilines (self, String, MaxCharLength):
+ Multilines = ''
+ StringLength = len(String)
+ CurrentStringStart = 0
+ StringOffset = 0
+ BreakLineDict = []
+ if len(String) <= MaxCharLength:
+ while (StringOffset < StringLength):
+ if StringOffset >= 1:
+ if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
+ BreakLineDict.append (StringOffset + 1)
+ StringOffset += 1
+ if BreakLineDict != []:
+ for Each in BreakLineDict:
+ Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
+ CurrentStringStart = Each
+ if StringLength - CurrentStringStart > 0:
+ Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
+ else:
+ Multilines = " %s\n" % String
+ else:
+ NewLineStart = 0
+ NewLineCount = 0
+ FoundSpaceChar = False
+ while (StringOffset < StringLength):
+ if StringOffset >= 1:
+ if NewLineCount >= MaxCharLength - 1:
+ if String[StringOffset] == ' ' and StringLength - StringOffset > 10:
+ BreakLineDict.append (NewLineStart + NewLineCount)
+ NewLineStart = NewLineStart + NewLineCount
+ NewLineCount = 0
+ FoundSpaceChar = True
+ elif StringOffset == StringLength - 1 and FoundSpaceChar == False:
+ BreakLineDict.append (0)
+ if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
+ BreakLineDict.append (StringOffset + 1)
+ NewLineStart = StringOffset + 1
+ NewLineCount = 0
+ StringOffset += 1
+ NewLineCount += 1
+ if BreakLineDict != []:
+ BreakLineDict.sort ()
+ for Each in BreakLineDict:
+ if Each > 0:
+ Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
+ CurrentStringStart = Each
+ if StringLength - CurrentStringStart > 0:
+ Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
+ return Multilines
+
+ def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option, BitsLength = None):
+ PosName = 28
+ PosComment = 30
+ NameLine=''
+ HelpLine=''
+ OptionLine=''
+
+ if Length == 0 and Name == 'Dummy':
+ return '\n'
+
+ IsArray = False
+ if Length in [1,2,4,8]:
+ Type = "UINT%d" % (Length * 8)
+ if Name.startswith("UnusedUpdSpace") and Length != 1:
+ IsArray = True
+ Type = "UINT8"
+ else:
+ IsArray = True
+ Type = "UINT8"
+
+ if Item and Item['value'].startswith('{'):
+ Type = "UINT8"
+ IsArray = True
+
+ if Struct != '':
+ Type = Struct
+ if Struct in ['UINT8','UINT16','UINT32','UINT64']:
+ IsArray = True
+ Unit = int(Type[4:]) / 8
+ Length = Length / Unit
+ else:
+ IsArray = False
+
+ if IsArray:
+ Name = Name + '[%d]' % Length
+
+ if len(Type) < PosName:
+ Space1 = PosName - len(Type)
+ else:
+ Space1 = 1
+
+ if BsfName != '':
+ NameLine=" - %s\n" % BsfName
+ else:
+ NameLine="\n"
+
+ if Help != '':
+ HelpLine = self.ProcessMultilines (Help, 80)
+
+ if Option != '':
+ OptionLine = self.ProcessMultilines (Option, 80)
+
+ if Offset is None:
+ OffsetStr = '????'
+ else:
+ OffsetStr = '0x%04X' % Offset
+
+ if BitsLength is None:
+ BitsLength = ''
+ else:
+ BitsLength = ' : %d' % BitsLength
+
+ return "\n/** Offset %s%s%s%s**/\n %s%s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name, BitsLength)
+
+ def PostProcessBody (self, TextBody):
+ NewTextBody = []
+ OldTextBody = []
+ IncludeLine = False
+ StructName = ''
+ VariableName = ''
+ IsUpdHdrDefined = False
+ IsUpdHeader = False
+ for Line in TextBody:
+ SplitToLines = Line.splitlines()
+ MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0])
+ if MatchComment:
+ if MatchComment.group(1) == 'FSP_UPD_HEADER':
+ IsUpdHeader = True
+ else:
+ IsUpdHeader = False
+ if IsUpdHdrDefined != True or IsUpdHeader != True:
+ CommentLine = " " + MatchComment.group(2) + "\n"
+ NewTextBody.append("/**" + CommentLine + "**/\n")
+ Line = Line[(len(SplitToLines[0]) + 1):]
+
+ Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line)
+ if Match:
+ Line = Match.group(4)
+ if Match.group(1) == 'FSP_UPD_HEADER':
+ IsUpdHeader = True
+ else:
+ IsUpdHeader = False
+
+ if Match and Match.group(3) == 'START':
+ if IsUpdHdrDefined != True or IsUpdHeader != True:
+ NewTextBody.append ('typedef struct {\n')
+ StructName = Match.group(1)
+ VariableName = Match.group(2)
+ MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line)
+ if MatchOffset:
+ Offset = int(MatchOffset.group(1), 16)
+ else:
+ Offset = None
+ Line
+ IncludeLine = True
+ OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', ''))
+ if IncludeLine:
+ if IsUpdHdrDefined != True or IsUpdHeader != True:
+ NewTextBody.append (Line)
+ else:
+ OldTextBody.append (Line)
+
+ if Match and Match.group(3) == 'END':
+ if (StructName != Match.group(1)) or (VariableName != Match.group(2)):
+ print ("Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1)))
+ else:
+ if IsUpdHdrDefined != True or IsUpdHeader != True:
+ NewTextBody.append ('} %s;\n\n' % StructName)
+ IsUpdHdrDefined = True
+ IncludeLine = False
+ NewTextBody.extend(OldTextBody)
+ return NewTextBody
+
+ def WriteLinesWithoutTailingSpace (self, HeaderFd, Line):
+ TxtBody2 = Line.splitlines(True)
+ for Line2 in TxtBody2:
+ Line2 = Line2.rstrip()
+ Line2 += '\n'
+ HeaderFd.write (Line2)
+ return 0
+ def CreateHeaderFile (self, InputHeaderFile):
+ FvDir = self._FvDir
+
+ HeaderFileName = 'FspUpd.h'
+ HeaderFile = os.path.join(FvDir, HeaderFileName)
+
+ # Check if header needs to be recreated
+ if (self.NoDscFileChange (HeaderFile)):
+ # DSC has not been modified yet
+ # So don't have to re-generate other files
+ self.Error = 'No DSC file change, skip to create UPD header file'
+ return 256
+
+ TxtBody = []
+ for Item in self._CfgItemList:
+ if str(Item['cname']) == 'Signature' and Item['length'] == 8:
+ Value = int(Item['value'], 16)
+ Chars = []
+ while Value != 0x0:
+ Chars.append(chr(Value & 0xFF))
+ Value = Value >> 8
+ SignatureStr = ''.join(Chars)
+ # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly
+ if '_T' in SignatureStr[6:6+2]:
+ TxtBody.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
+ elif '_M' in SignatureStr[6:6+2]:
+ TxtBody.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
+ elif '_S' in SignatureStr[6:6+2]:
+ TxtBody.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr))
+ TxtBody.append("\n")
+
+ for Region in ['UPD']:
+ UpdOffsetTable = []
+ UpdSignature = ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS
+ UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']
+ for Item in self._CfgItemList:
+ if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:
+ Item["offset"] = 0 # re-initialize offset to 0 when new UPD structure starting
+ UpdOffsetTable.append (Item["offset"])
+
+ for UpdIdx in range(len(UpdOffsetTable)):
+ CommentLine = ""
+ for Item in self._CfgItemList:
+ if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]:
+ MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"])
+ if MatchComment and MatchComment.group(1) == Region[0]:
+ CommentLine = " " + MatchComment.group(2) + "\n"
+ TxtBody.append("/**" + CommentLine + "**/\n")
+ elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '':
+ Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx])
+ if Match:
+ TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n")
+ TxtBody.append("typedef struct {\n")
+ NextOffset = 0
+ SpaceIdx = 0
+ Offset = 0
+
+ LastVisible = True
+ ResvOffset = 0
+ ResvIdx = 0
+ LineBuffer = []
+ InRange = False
+ for Item in self._CfgItemList:
+ if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V':
+ InRange = True
+ if InRange != True:
+ continue
+ if Item['cname'] == 'UpdTerminator':
+ InRange = False
+
+ if Item['region'] != Region:
+ continue
+
+ if Item["offset"] < UpdOffsetTable[UpdIdx]:
+ continue
+
+ NextVisible = LastVisible
+
+ if LastVisible and (Item['header'] == 'OFF'):
+ NextVisible = False
+ ResvOffset = Item['offset']
+ elif (not LastVisible) and Item['header'] == 'ON':
+ NextVisible = True
+ Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx
+ ResvIdx = ResvIdx + 1
+ TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', ''))
+
+ if Offset < Item["offset"]:
+ if LastVisible:
+ Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx
+ LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', ''))
+ SpaceIdx = SpaceIdx + 1
+ Offset = Item["offset"]
+
+ LastVisible = NextVisible
+
+ Offset = Offset + Item["length"]
+ if LastVisible:
+ for Each in LineBuffer:
+ TxtBody.append (Each)
+ LineBuffer = []
+ Comment = Item["comment"]
+ Embed = Item["embed"].upper()
+ if Embed.endswith(':START') or Embed.endswith(':END'):
+ if not Comment == '' and Embed.endswith(':START'):
+ Marker = '/* COMMENT:%s */ \n' % Item["comment"]
+ Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"]
+ else:
+ Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"]
+ else:
+ if Embed == '':
+ Marker = ''
+ else:
+ self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"]
+ return 4
+ Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option'])
+ TxtBody.append(Line)
+ if Item['cname'] == 'UpdTerminator':
+ break
+ TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n")
+
+ # Handle the embedded data structure
+ TxtBody = self.PostProcessBody (TxtBody)
+
+ HeaderTFileName = 'FsptUpd.h'
+ HeaderMFileName = 'FspmUpd.h'
+ HeaderSFileName = 'FspsUpd.h'
+
+ UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION
+ UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG
+ UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']
+ ExcludedSpecificUpd = ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD']
+
+ IncLines = []
+ if InputHeaderFile != '':
+ if not os.path.exists(InputHeaderFile):
+ self.Error = "Input header file '%s' does not exist" % InputHeaderFile
+ return 6
+
+ InFd = open(InputHeaderFile, "r")
+ IncLines = InFd.readlines()
+ InFd.close()
+
+ for item in range(len(UpdRegionCheck)):
+ if UpdRegionCheck[item] == 'FSPT':
+ HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w")
+ FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName))
+ elif UpdRegionCheck[item] == 'FSPM':
+ HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w")
+ FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName))
+ elif UpdRegionCheck[item] == 'FSPS':
+ HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w")
+ FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName))
+ FileName = FileBase.replace(".", "_").upper()
+ HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))
+ HeaderFd.write("#ifndef __%s__\n" % FileName)
+ HeaderFd.write("#define __%s__\n\n" % FileName)
+ HeaderFd.write("#include <%s>\n\n" % HeaderFileName)
+ HeaderFd.write("#pragma pack(1)\n\n")
+
+ Export = False
+ for Line in IncLines:
+ Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line)
+ if Match:
+ if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]:
+ Export = True
+ continue
+ else:
+ Export = False
+ continue
+ if Export:
+ HeaderFd.write(Line)
+ HeaderFd.write("\n")
+
+ Index = 0
+ StartIndex = 0
+ EndIndex = 0
+ StructStart = []
+ StructStartWithComment = []
+ StructEnd = []
+ for Line in TxtBody:
+ Index += 1
+ Match = re.match("(typedef struct {)", Line)
+ if Match:
+ StartIndex = Index - 1
+ Match = re.match("}\s([_A-Z0-9]+);", Line)
+ if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd[item] not in Match.group(1)):
+ EndIndex = Index
+ StructStart.append(StartIndex)
+ StructEnd.append(EndIndex)
+ Index = 0
+ for Line in TxtBody:
+ Index += 1
+ for Item in range(len(StructStart)):
+ if Index == StructStart[Item]:
+ Match = re.match("^(/\*\*\s*)", Line)
+ if Match:
+ StructStartWithComment.append(StructStart[Item])
+ else:
+ StructStartWithComment.append(StructStart[Item] + 1)
+ Index = 0
+ for Line in TxtBody:
+ Index += 1
+ for Item in range(len(StructStart)):
+ if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:
+ self.WriteLinesWithoutTailingSpace(HeaderFd, Line)
+ HeaderFd.write("#pragma pack()\n\n")
+ HeaderFd.write("#endif\n")
+ HeaderFd.close()
+
+ HeaderFd = open(HeaderFile, "w")
+ FileBase = os.path.basename(HeaderFile)
+ FileName = FileBase.replace(".", "_").upper()
+ HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year))
+ HeaderFd.write("#ifndef __%s__\n" % FileName)
+ HeaderFd.write("#define __%s__\n\n" % FileName)
+ HeaderFd.write("#include <FspEas.h>\n\n")
+ HeaderFd.write("#pragma pack(1)\n\n")
+
+ for item in range(len(UpdRegionCheck)):
+ Index = 0
+ StartIndex = 0
+ EndIndex = 0
+ StructStart = []
+ StructStartWithComment = []
+ StructEnd = []
+ for Line in TxtBody:
+ Index += 1
+ Match = re.match("(typedef struct {)", Line)
+ if Match:
+ StartIndex = Index - 1
+ Match = re.match("#define\s([_A-Z0-9]+)\s*", Line)
+ if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)):
+ StructStart.append(Index - 1)
+ StructEnd.append(Index)
+ Index = 0
+ for Line in TxtBody:
+ Index += 1
+ for Item in range(len(StructStart)):
+ if Index == StructStart[Item]:
+ Match = re.match("^(/\*\*\s*)", Line)
+ if Match:
+ StructStartWithComment.append(StructStart[Item])
+ else:
+ StructStartWithComment.append(StructStart[Item] + 1)
+ Index = 0
+ for Line in TxtBody:
+ Index += 1
+ for Item in range(len(StructStart)):
+ if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]:
+ self.WriteLinesWithoutTailingSpace(HeaderFd, Line)
+ HeaderFd.write("#pragma pack()\n\n")
+ HeaderFd.write("#endif\n")
+ HeaderFd.close()
+
+ return 0
+
+ def WriteBsfStruct (self, BsfFd, Item):
+ LogExpr = CLogicalExpression()
+ if Item['type'] == "None":
+ Space = "gPlatformFspPkgTokenSpaceGuid"
+ else:
+ Space = Item['space']
+ Line = " $%s_%s" % (Space, Item['cname'])
+ Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value'])
+ if Match:
+ DefaultValue = Match.group(1).strip()
+ else:
+ DefaultValue = Item['value'].strip()
+ if 'bitlength' in Item:
+ BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue))
+ else:
+ BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue))
+ TmpList = []
+ if Item['type'] == "Combo":
+ if not Item['option'] in self._BuidinOption:
+ OptList = Item['option'].split(',')
+ for Option in OptList:
+ Option = Option.strip()
+ (OpVal, OpStr) = Option.split(':')
+ test = LogExpr.getNumber (OpVal)
+ if test is None:
+ raise Exception("Selection Index '%s' is not a number" % OpVal)
+ TmpList.append((OpVal, OpStr))
+ return TmpList
+
+ def WriteBsfOption (self, BsfFd, Item):
+ PcdName = Item['space'] + '_' + Item['cname']
+ WriteHelp = 0
+ if Item['type'] == "Combo":
+ if Item['option'] in self._BuidinOption:
+ Options = self._BuidinOption[Item['option']]
+ else:
+ Options = PcdName
+ BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options))
+ WriteHelp = 1
+ elif Item['type'].startswith("EditNum"):
+ Match = re.match("EditNum\s*,\s*(HEX|DEC)\s*,\s*\((\d+|0x[0-9A-Fa-f]+)\s*,\s*(\d+|0x[0-9A-Fa-f]+)\)", Item['type'])
+ if Match:
+ BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1)))
+ WriteHelp = 2
+ elif Item['type'].startswith("EditText"):
+ BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name']))
+ WriteHelp = 1
+ elif Item['type'] == "Table":
+ Columns = Item['option'].split(',')
+ if len(Columns) != 0:
+ BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name']))
+ for Col in Columns:
+ Fmt = Col.split(':')
+ if len(Fmt) != 3:
+ raise Exception("Column format '%s' is invalid !" % Fmt)
+ try:
+ Dtype = int(Fmt[1].strip())
+ except:
+ raise Exception("Column size '%s' is invalid !" % Fmt[1])
+ BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip()))
+ BsfFd.write(',\n')
+ WriteHelp = 1
+
+ if WriteHelp > 0:
+ HelpLines = Item['help'].split('\\n\\r')
+ FirstLine = True
+ for HelpLine in HelpLines:
+ if FirstLine:
+ FirstLine = False
+ BsfFd.write(' Help "%s"\n' % (HelpLine))
+ else:
+ BsfFd.write(' "%s"\n' % (HelpLine))
+ if WriteHelp == 2:
+ BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3)))
+
+ def GenerateBsfFile (self, BsfFile):
+
+ if BsfFile == '':
+ self.Error = "BSF output file '%s' is invalid" % BsfFile
+ return 1
+
+ if (self.NoDscFileChange (BsfFile)):
+ # DSC has not been modified yet
+ # So don't have to re-generate other files
+ self.Error = 'No DSC file change, skip to create UPD BSF file'
+ return 256
+
+ Error = 0
+ OptionDict = {}
+ BsfFd = open(BsfFile, "w")
+ BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year))
+ BsfFd.write("%s\n" % self._GlobalDataDef)
+ BsfFd.write("StructDef\n")
+ NextOffset = -1
+ for Item in self._CfgItemList:
+ if Item['find'] != '':
+ BsfFd.write('\n Find "%s"\n' % Item['find'])
+ NextOffset = Item['offset'] + Item['length']
+ if Item['name'] != '':
+ if NextOffset != Item['offset']:
+ BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset))
+ if len(Item['subreg']) > 0:
+ NextOffset = Item['offset']
+ BitsOffset = NextOffset * 8
+ for SubItem in Item['subreg']:
+ BitsOffset += SubItem['bitlength']
+ if SubItem['name'] == '':
+ if 'bitlength' in SubItem:
+ BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength']))
+ else:
+ BsfFd.write(" Skip %d bytes\n" % (SubItem['length']))
+ else:
+ Options = self.WriteBsfStruct(BsfFd, SubItem)
+ if len(Options) > 0:
+ OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options
+
+ NextBitsOffset = (Item['offset'] + Item['length']) * 8
+ if NextBitsOffset > BitsOffset:
+ BitsGap = NextBitsOffset - BitsOffset
+ BitsRemain = BitsGap % 8
+ if BitsRemain:
+ BsfFd.write(" Skip %d bits\n" % BitsRemain)
+ BitsGap -= BitsRemain
+ BytesRemain = int(BitsGap / 8)
+ if BytesRemain:
+ BsfFd.write(" Skip %d bytes\n" % BytesRemain)
+ NextOffset = Item['offset'] + Item['length']
+ else:
+ NextOffset = Item['offset'] + Item['length']
+ Options = self.WriteBsfStruct(BsfFd, Item)
+ if len(Options) > 0:
+ OptionDict[Item['space']+'_'+Item['cname']] = Options
+ BsfFd.write("\nEndStruct\n\n")
+
+ BsfFd.write("%s" % self._BuidinOptionTxt)
+
+ for Each in OptionDict:
+ BsfFd.write("List &%s\n" % Each)
+ for Item in OptionDict[Each]:
+ BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1]))
+ BsfFd.write("EndList\n\n")
+
+ BsfFd.write("BeginInfoBlock\n")
+ BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver']))
+ BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name']))
+ BsfFd.write("EndInfoBlock\n\n")
+
+ for Each in self._CfgPageDict:
+ BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each])
+ BsfItems = []
+ for Item in self._CfgItemList:
+ if Item['name'] != '':
+ if Item['page'] != Each:
+ continue
+ if len(Item['subreg']) > 0:
+ for SubItem in Item['subreg']:
+ if SubItem['name'] != '':
+ BsfItems.append(SubItem)
+ else:
+ BsfItems.append(Item)
+
+ BsfItems.sort(key=lambda x: x['order'])
+
+ for Item in BsfItems:
+ self.WriteBsfOption (BsfFd, Item)
+ BsfFd.write("EndPage\n\n")
+
+ BsfFd.close()
+ return Error
+
+
+def Usage():
+ print ("GenCfgOpt Version 0.56")
+ print ("Usage:")
+ print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]")
+ print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]")
+ print (" GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]")
+
+def Main():
+ #
+ # Parse the options and args
+ #
+ i = 1
+
+ GenCfgOpt = CGenCfgOpt()
+ while i < len(sys.argv):
+ if sys.argv[i].strip().lower() == "--pcd":
+ BuildOptionPcd.append(sys.argv[i+1])
+ i += 1
+ i += 1
+ argc = len(sys.argv)
+ if argc < 4:
+ Usage()
+ return 1
+ else:
+ DscFile = sys.argv[2]
+ if not os.path.exists(DscFile):
+ print ("ERROR: Cannot open DSC file '%s' !" % DscFile)
+ return 2
+
+ OutFile = ''
+ if argc > 4:
+ if sys.argv[4][0] == '-':
+ Start = 4
+ else:
+ OutFile = sys.argv[4]
+ Start = 5
+ if argc > Start:
+ if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0:
+ print ("ERROR: Macro parsing failed !")
+ return 3
+
+ FvDir = sys.argv[3]
+ if not os.path.exists(FvDir):
+ os.makedirs(FvDir)
+
+ if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0:
+ print ("ERROR: %s !" % GenCfgOpt.Error)
+ return 5
+
+ if GenCfgOpt.UpdateSubRegionDefaultValue() != 0:
+ print ("ERROR: %s !" % GenCfgOpt.Error)
+ return 7
+
+ if sys.argv[1] == "UPDTXT":
+ Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile)
+ if Ret != 0:
+ # No change is detected
+ if Ret == 256:
+ print ("INFO: %s !" % (GenCfgOpt.Error))
+ else :
+ print ("ERROR: %s !" % (GenCfgOpt.Error))
+ return Ret
+ elif sys.argv[1] == "HEADER":
+ Ret = GenCfgOpt.CreateHeaderFile(OutFile)
+ if Ret != 0:
+ # No change is detected
+ if Ret == 256:
+ print ("INFO: %s !" % (GenCfgOpt.Error))
+ else :
+ print ("ERROR: %s !" % (GenCfgOpt.Error))
+ return 8
+ return Ret
+ elif sys.argv[1] == "GENBSF":
+ Ret = GenCfgOpt.GenerateBsfFile(OutFile)
+ if Ret != 0:
+ # No change is detected
+ if Ret == 256:
+ print ("INFO: %s !" % (GenCfgOpt.Error))
+ else :
+ print ("ERROR: %s !" % (GenCfgOpt.Error))
+ return 9
+ return Ret
+ else:
+ if argc < 5:
+ Usage()
+ return 1
+ print ("ERROR: Unknown command '%s' !" % sys.argv[1])
+ Usage()
+ return 1
+ return 0
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(Main())
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/PatchFv.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/PatchFv.py
new file mode 100755
index 00000000..adec12ea
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/PatchFv.py
@@ -0,0 +1,954 @@
+## @ PatchFv.py
+#
+# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+import os
+import re
+import sys
+
+#
+# Read data from file
+#
+# param [in] binfile Binary file
+# param [in] offset Offset
+# param [in] len Length
+#
+# retval value Value
+#
+def readDataFromFile (binfile, offset, len=1):
+ fd = open(binfile, "r+b")
+ fsize = os.path.getsize(binfile)
+ offval = offset & 0xFFFFFFFF
+ if (offval & 0x80000000):
+ offval = fsize - (0xFFFFFFFF - offval + 1)
+ fd.seek(offval)
+ if sys.version_info[0] < 3:
+ bytearray = [ord(b) for b in fd.read(len)]
+ else:
+ bytearray = [b for b in fd.read(len)]
+ value = 0
+ idx = len - 1
+ while idx >= 0:
+ value = value << 8 | bytearray[idx]
+ idx = idx - 1
+ fd.close()
+ return value
+
+#
+# Check FSP header is valid or not
+#
+# param [in] binfile Binary file
+#
+# retval boolean True: valid; False: invalid
+#
+def IsFspHeaderValid (binfile):
+ fd = open (binfile, "rb")
+ bindat = fd.read(0x200) # only read first 0x200 bytes
+ fd.close()
+ HeaderList = [b'FSPH' , b'FSPP' , b'FSPE'] # Check 'FSPH', 'FSPP', and 'FSPE' in the FSP header
+ OffsetList = []
+ for each in HeaderList:
+ if each in bindat:
+ idx = bindat.index(each)
+ else:
+ idx = 0
+ OffsetList.append(idx)
+ if not OffsetList[0] or not OffsetList[1]: # If 'FSPH' or 'FSPP' is missing, it will return false
+ return False
+ if sys.version_info[0] < 3:
+ Revision = ord(bindat[OffsetList[0] + 0x0B])
+ else:
+ Revision = bindat[OffsetList[0] + 0x0B]
+ #
+ # if revision is bigger than 1, it means it is FSP v1.1 or greater revision, which must contain 'FSPE'.
+ #
+ if Revision > 1 and not OffsetList[2]:
+ return False # If FSP v1.1 or greater without 'FSPE', then return false
+ return True
+
+#
+# Patch data in file
+#
+# param [in] binfile Binary file
+# param [in] offset Offset
+# param [in] value Patch value
+# param [in] len Length
+#
+# retval len Length
+#
+def patchDataInFile (binfile, offset, value, len=1):
+ fd = open(binfile, "r+b")
+ fsize = os.path.getsize(binfile)
+ offval = offset & 0xFFFFFFFF
+ if (offval & 0x80000000):
+ offval = fsize - (0xFFFFFFFF - offval + 1)
+ bytearray = []
+ idx = 0
+ while idx < len:
+ bytearray.append(value & 0xFF)
+ value = value >> 8
+ idx = idx + 1
+ fd.seek(offval)
+ if sys.version_info[0] < 3:
+ fd.write("".join(chr(b) for b in bytearray))
+ else:
+ fd.write(bytes(bytearray))
+ fd.close()
+ return len
+
+
+class Symbols:
+ def __init__(self):
+ self.dictSymbolAddress = {}
+ self.dictGuidNameXref = {}
+ self.dictFfsOffset = {}
+ self.dictVariable = {}
+ self.dictModBase = {}
+ self.fdFile = None
+ self.string = ""
+ self.fdBase = 0xFFFFFFFF
+ self.fdSize = 0
+ self.index = 0
+ self.fvList = []
+ self.parenthesisOpenSet = '([{<'
+ self.parenthesisCloseSet = ')]}>'
+
+ #
+ # Get FD file
+ #
+ # retval self.fdFile Retrieve FD file
+ #
+ def getFdFile (self):
+ return self.fdFile
+
+ #
+ # Get FD size
+ #
+ # retval self.fdSize Retrieve the size of FD file
+ #
+ def getFdSize (self):
+ return self.fdSize
+
+ def parseFvInfFile (self, infFile):
+ fvInfo = {}
+ fvFile = infFile[0:-4] + ".Fv"
+ fvInfo['Name'] = os.path.splitext(os.path.basename(infFile))[0]
+ fvInfo['Offset'] = self.getFvOffsetInFd(fvFile)
+ fvInfo['Size'] = readDataFromFile (fvFile, 0x20, 4)
+ fdIn = open(infFile, "r")
+ rptLines = fdIn.readlines()
+ fdIn.close()
+ fvInfo['Base'] = 0
+ for rptLine in rptLines:
+ match = re.match("^EFI_BASE_ADDRESS\s*=\s*(0x[a-fA-F0-9]+)", rptLine)
+ if match:
+ fvInfo['Base'] = int(match.group(1), 16)
+ break
+ self.fvList.append(dict(fvInfo))
+ return 0
+
+ #
+ # Create dictionaries
+ #
+ # param [in] fvDir FV's directory
+ # param [in] fvNames All FV's names
+ #
+ # retval 0 Created dictionaries successfully
+ #
+ def createDicts (self, fvDir, fvNames):
+ #
+ # If the fvDir is not a directory, then raise an exception
+ #
+ if not os.path.isdir(fvDir):
+ raise Exception ("'%s' is not a valid directory!" % fvDir)
+
+ #
+ # If the Guid.xref is not existing in fvDir, then raise an exception
+ #
+ xrefFile = os.path.join(fvDir, "Guid.xref")
+ if not os.path.exists(xrefFile):
+ raise Exception("Cannot open GUID Xref file '%s'!" % xrefFile)
+
+ #
+ # Add GUID reference to dictionary
+ #
+ self.dictGuidNameXref = {}
+ self.parseGuidXrefFile(xrefFile)
+
+ #
+ # Split up each FV from fvNames and get the fdBase
+ #
+ fvList = fvNames.split(":")
+ fdBase = fvList.pop()
+ if len(fvList) == 0:
+ fvList.append(fdBase)
+
+ #
+ # If the FD file is not existing, then raise an exception
+ #
+ fdFile = os.path.join(fvDir, fdBase.strip() + ".fd")
+ if not os.path.exists(fdFile):
+ raise Exception("Cannot open FD file '%s'!" % fdFile)
+
+ #
+ # Get the size of the FD file
+ #
+ self.fdFile = fdFile
+ self.fdSize = os.path.getsize(fdFile)
+
+ #
+ # If the INF file, which is the first element of fvList, is not existing, then raise an exception
+ #
+ infFile = os.path.join(fvDir, fvList[0].strip()) + ".inf"
+ if not os.path.exists(infFile):
+ raise Exception("Cannot open INF file '%s'!" % infFile)
+
+ #
+ # Parse INF file in order to get fdBase and then assign those values to dictVariable
+ #
+ self.parseInfFile(infFile)
+ self.dictVariable = {}
+ self.dictVariable["FDSIZE"] = self.fdSize
+ self.dictVariable["FDBASE"] = self.fdBase
+
+ #
+ # Collect information from FV MAP file and FV TXT file then
+ # put them into dictionaries
+ #
+ self.fvList = []
+ self.dictSymbolAddress = {}
+ self.dictFfsOffset = {}
+ for file in fvList:
+
+ #
+ # If the .Fv.map file is not existing, then raise an exception.
+ # Otherwise, parse FV MAP file
+ #
+ fvFile = os.path.join(fvDir, file.strip()) + ".Fv"
+ mapFile = fvFile + ".map"
+ if not os.path.exists(mapFile):
+ raise Exception("Cannot open MAP file '%s'!" % mapFile)
+
+ infFile = fvFile[0:-3] + ".inf"
+ self.parseFvInfFile(infFile)
+ self.parseFvMapFile(mapFile)
+
+ #
+ # If the .Fv.txt file is not existing, then raise an exception.
+ # Otherwise, parse FV TXT file
+ #
+ fvTxtFile = fvFile + ".txt"
+ if not os.path.exists(fvTxtFile):
+ raise Exception("Cannot open FV TXT file '%s'!" % fvTxtFile)
+
+ self.parseFvTxtFile(fvTxtFile)
+
+ for fv in self.fvList:
+ self.dictVariable['_BASE_%s_' % fv['Name']] = fv['Base']
+ #
+ # Search all MAP files in FFS directory if it exists then parse MOD MAP file
+ #
+ ffsDir = os.path.join(fvDir, "Ffs")
+ if (os.path.isdir(ffsDir)):
+ for item in os.listdir(ffsDir):
+ if len(item) <= 0x24:
+ continue
+ mapFile =os.path.join(ffsDir, item, "%s.map" % item[0:0x24])
+ if not os.path.exists(mapFile):
+ continue
+ self.parseModMapFile(item[0x24:], mapFile)
+
+ return 0
+
+ #
+ # Get FV offset in FD file
+ #
+ # param [in] fvFile FV file
+ #
+ # retval offset Got FV offset successfully
+ #
+ def getFvOffsetInFd(self, fvFile):
+ #
+ # Check if the first 0x70 bytes of fvFile can be found in fdFile
+ #
+ fvHandle = open(fvFile, "r+b")
+ fdHandle = open(self.fdFile, "r+b")
+ offset = fdHandle.read().find(fvHandle.read(0x70))
+ fvHandle.close()
+ fdHandle.close()
+ if offset == -1:
+ raise Exception("Could not locate FV file %s in FD!" % fvFile)
+ return offset
+
+ #
+ # Parse INF file
+ #
+ # param [in] infFile INF file
+ #
+ # retval 0 Parsed INF file successfully
+ #
+ def parseInfFile(self, infFile):
+ #
+ # Get FV offset and search EFI_BASE_ADDRESS in the FD file
+ # then assign the value of EFI_BASE_ADDRESS to fdBase
+ #
+ fvOffset = self.getFvOffsetInFd(infFile[0:-4] + ".Fv")
+ fdIn = open(infFile, "r")
+ rptLine = fdIn.readline()
+ self.fdBase = 0xFFFFFFFF
+ while (rptLine != "" ):
+ #EFI_BASE_ADDRESS = 0xFFFDF400
+ match = re.match("^EFI_BASE_ADDRESS\s*=\s*(0x[a-fA-F0-9]+)", rptLine)
+ if match is not None:
+ self.fdBase = int(match.group(1), 16) - fvOffset
+ rptLine = fdIn.readline()
+ fdIn.close()
+ if self.fdBase == 0xFFFFFFFF:
+ raise Exception("Could not find EFI_BASE_ADDRESS in INF file!" % fvFile)
+ return 0
+
+ #
+ # Parse FV TXT file
+ #
+ # param [in] fvTxtFile .Fv.txt file
+ #
+ # retval 0 Parsed FV TXT file successfully
+ #
+ def parseFvTxtFile(self, fvTxtFile):
+ fvName = os.path.basename(fvTxtFile)[0:-7].upper()
+ #
+ # Get information from .Fv.txt in order to create a dictionary
+ # For example,
+ # self.dictFfsOffset[912740BE-2284-4734-B971-84B027353F0C] = 0x000D4078
+ #
+ fvOffset = self.getFvOffsetInFd(fvTxtFile[0:-4])
+ fdIn = open(fvTxtFile, "r")
+ rptLine = fdIn.readline()
+ while (rptLine != "" ):
+ match = re.match("(0x[a-fA-F0-9]+)\s([0-9a-fA-F\-]+)", rptLine)
+ if match is not None:
+ if match.group(2) in self.dictFfsOffset:
+ self.dictFfsOffset[fvName + ':' + match.group(2)] = "0x%08X" % (int(match.group(1), 16) + fvOffset)
+ else:
+ self.dictFfsOffset[match.group(2)] = "0x%08X" % (int(match.group(1), 16) + fvOffset)
+ rptLine = fdIn.readline()
+ fdIn.close()
+ return 0
+
+ #
+ # Parse FV MAP file
+ #
+ # param [in] mapFile .Fv.map file
+ #
+ # retval 0 Parsed FV MAP file successfully
+ #
+ def parseFvMapFile(self, mapFile):
+ #
+ # Get information from .Fv.map in order to create dictionaries
+ # For example,
+ # self.dictModBase[FspSecCore:BASE] = 4294592776 (0xfffa4908)
+ # self.dictModBase[FspSecCore:ENTRY] = 4294606552 (0xfffa7ed8)
+ # self.dictModBase[FspSecCore:TEXT] = 4294593080 (0xfffa4a38)
+ # self.dictModBase[FspSecCore:DATA] = 4294612280 (0xfffa9538)
+ # self.dictSymbolAddress[FspSecCore:_SecStartup] = 0x00fffa4a38
+ #
+ fdIn = open(mapFile, "r")
+ rptLine = fdIn.readline()
+ modName = ""
+ foundModHdr = False
+ while (rptLine != "" ):
+ if rptLine[0] != ' ':
+ #DxeIpl (Fixed Flash Address, BaseAddress=0x00fffb4310, EntryPoint=0x00fffb4958,Type=PE)
+ match = re.match("([_a-zA-Z0-9\-]+)\s\(.+BaseAddress=(0x[0-9a-fA-F]+),\s+EntryPoint=(0x[0-9a-fA-F]+),\s*Type=\w+\)", rptLine)
+ if match is None:
+ #DxeIpl (Fixed Flash Address, BaseAddress=0x00fffb4310, EntryPoint=0x00fffb4958)
+ match = re.match("([_a-zA-Z0-9\-]+)\s\(.+BaseAddress=(0x[0-9a-fA-F]+),\s+EntryPoint=(0x[0-9a-fA-F]+)\)", rptLine)
+ if match is not None:
+ foundModHdr = True
+ modName = match.group(1)
+ if len(modName) == 36:
+ modName = self.dictGuidNameXref[modName.upper()]
+ self.dictModBase['%s:BASE' % modName] = int (match.group(2), 16)
+ self.dictModBase['%s:ENTRY' % modName] = int (match.group(3), 16)
+ #(GUID=86D70125-BAA3-4296-A62F-602BEBBB9081 .textbaseaddress=0x00fffb4398 .databaseaddress=0x00fffb4178)
+ match = re.match("\(GUID=([A-Z0-9\-]+)\s+\.textbaseaddress=(0x[0-9a-fA-F]+)\s+\.databaseaddress=(0x[0-9a-fA-F]+)\)", rptLine)
+ if match is not None:
+ if foundModHdr:
+ foundModHdr = False
+ else:
+ modName = match.group(1)
+ if len(modName) == 36:
+ modName = self.dictGuidNameXref[modName.upper()]
+ self.dictModBase['%s:TEXT' % modName] = int (match.group(2), 16)
+ self.dictModBase['%s:DATA' % modName] = int (match.group(3), 16)
+ else:
+ # 0x00fff8016c __ModuleEntryPoint
+ foundModHdr = False
+ match = re.match("^\s+(0x[a-z0-9]+)\s+([_a-zA-Z0-9]+)", rptLine)
+ if match is not None:
+ self.dictSymbolAddress["%s:%s"%(modName, match.group(2))] = match.group(1)
+ rptLine = fdIn.readline()
+ fdIn.close()
+ return 0
+
+ #
+ # Parse MOD MAP file
+ #
+ # param [in] moduleName Module name
+ # param [in] mapFile .Fv.map file
+ #
+ # retval 0 Parsed MOD MAP file successfully
+ # retval 1 There is no moduleEntryPoint in modSymbols
+ #
+ def parseModMapFile(self, moduleName, mapFile):
+ #
+ # Get information from mapFile by moduleName in order to create a dictionary
+ # For example,
+ # self.dictSymbolAddress[FspSecCore:___guard_fids_count] = 0x00fffa4778
+ #
+ modSymbols = {}
+ fdIn = open(mapFile, "r")
+ reportLines = fdIn.readlines()
+ fdIn.close()
+
+ moduleEntryPoint = "__ModuleEntryPoint"
+ reportLine = reportLines[0]
+ if reportLine.strip().find("Archive member included") != -1:
+ #GCC
+ # 0x0000000000001d55 IoRead8
+ patchMapFileMatchString = "\s+(0x[0-9a-fA-F]{16})\s+([^\s][^0x][_a-zA-Z0-9\-]+)\s"
+ matchKeyGroupIndex = 2
+ matchSymbolGroupIndex = 1
+ prefix = '_'
+ else:
+ #MSFT
+ #0003:00000190 _gComBase 00007a50 SerialPo
+ patchMapFileMatchString = "^\s[0-9a-fA-F]{4}:[0-9a-fA-F]{8}\s+(\w+)\s+([0-9a-fA-F]{8}\s+)"
+ matchKeyGroupIndex = 1
+ matchSymbolGroupIndex = 2
+ prefix = ''
+
+ for reportLine in reportLines:
+ match = re.match(patchMapFileMatchString, reportLine)
+ if match is not None:
+ modSymbols[prefix + match.group(matchKeyGroupIndex)] = match.group(matchSymbolGroupIndex)
+
+ # Handle extra module patchable PCD variable in Linux map since it might have different format
+ # .data._gPcd_BinaryPatch_PcdVpdBaseAddress
+ # 0x0000000000003714 0x4 /tmp/ccmytayk.ltrans1.ltrans.o
+ handleNext = False
+ if matchSymbolGroupIndex == 1:
+ for reportLine in reportLines:
+ if handleNext:
+ handleNext = False
+ pcdName = match.group(1)
+ match = re.match("\s+(0x[0-9a-fA-F]{16})\s+", reportLine)
+ if match is not None:
+ modSymbols[prefix + pcdName] = match.group(1)
+ else:
+ match = re.match("^\s\.data\.(_gPcd_BinaryPatch[_a-zA-Z0-9\-]+)", reportLine)
+ if match is not None:
+ handleNext = True
+ continue
+
+ if not moduleEntryPoint in modSymbols:
+ return 1
+
+ modEntry = '%s:%s' % (moduleName,moduleEntryPoint)
+ if not modEntry in self.dictSymbolAddress:
+ modKey = '%s:ENTRY' % moduleName
+ if modKey in self.dictModBase:
+ baseOffset = self.dictModBase['%s:ENTRY' % moduleName] - int(modSymbols[moduleEntryPoint], 16)
+ else:
+ return 2
+ else:
+ baseOffset = int(self.dictSymbolAddress[modEntry], 16) - int(modSymbols[moduleEntryPoint], 16)
+ for symbol in modSymbols:
+ fullSym = "%s:%s" % (moduleName, symbol)
+ if not fullSym in self.dictSymbolAddress:
+ self.dictSymbolAddress[fullSym] = "0x00%08x" % (baseOffset+ int(modSymbols[symbol], 16))
+ return 0
+
+ #
+ # Parse Guid.xref file
+ #
+ # param [in] xrefFile the full directory of Guid.xref file
+ #
+ # retval 0 Parsed Guid.xref file successfully
+ #
+ def parseGuidXrefFile(self, xrefFile):
+ #
+ # Get information from Guid.xref in order to create a GuidNameXref dictionary
+ # The dictGuidNameXref, for example, will be like
+ # dictGuidNameXref [1BA0062E-C779-4582-8566-336AE8F78F09] = FspSecCore
+ #
+ fdIn = open(xrefFile, "r")
+ rptLine = fdIn.readline()
+ while (rptLine != "" ):
+ match = re.match("([0-9a-fA-F\-]+)\s([_a-zA-Z0-9]+)", rptLine)
+ if match is not None:
+ self.dictGuidNameXref[match.group(1).upper()] = match.group(2)
+ rptLine = fdIn.readline()
+ fdIn.close()
+ return 0
+
+ #
+ # Get current character
+ #
+ # retval elf.string[self.index]
+ # retval '' Exception
+ #
+ def getCurr(self):
+ try:
+ return self.string[self.index]
+ except Exception:
+ return ''
+
+ #
+ # Check to see if it is last index
+ #
+ # retval self.index
+ #
+ def isLast(self):
+ return self.index == len(self.string)
+
+ #
+ # Move to next index
+ #
+ def moveNext(self):
+ self.index += 1
+
+ #
+ # Skip space
+ #
+ def skipSpace(self):
+ while not self.isLast():
+ if self.getCurr() in ' \t':
+ self.moveNext()
+ else:
+ return
+
+ #
+ # Parse value
+ #
+ # retval value
+ #
+ def parseValue(self):
+ self.skipSpace()
+ var = ''
+ while not self.isLast():
+ char = self.getCurr()
+ if char.lower() in '_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:-':
+ var += char
+ self.moveNext()
+ else:
+ break
+
+ if ':' in var:
+ partList = var.split(':')
+ lenList = len(partList)
+ if lenList != 2 and lenList != 3:
+ raise Exception("Unrecognized expression %s" % var)
+ modName = partList[lenList-2]
+ modOff = partList[lenList-1]
+ if ('-' not in modName) and (modOff[0] in '0123456789'):
+ # MOD: OFFSET
+ var = self.getModGuid(modName) + ":" + modOff
+ if '-' in var: # GUID:OFFSET
+ value = self.getGuidOff(var)
+ else:
+ value = self.getSymbols(var)
+ self.synUsed = True
+ else:
+ if var[0] in '0123456789':
+ value = self.getNumber(var)
+ else:
+ value = self.getVariable(var)
+ return int(value)
+
+ #
+ # Parse single operation
+ #
+ # retval ~self.parseBrace() or self.parseValue()
+ #
+ def parseSingleOp(self):
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '~':
+ self.moveNext()
+ return ~self.parseBrace()
+ else:
+ return self.parseValue()
+
+ #
+ # Parse symbol of Brace([, {, <)
+ #
+ # retval value or self.parseSingleOp()
+ #
+ def parseBrace(self):
+ self.skipSpace()
+ char = self.getCurr()
+ parenthesisType = self.parenthesisOpenSet.find(char)
+ if parenthesisType >= 0:
+ self.moveNext()
+ value = self.parseExpr()
+ self.skipSpace()
+ if self.getCurr() != self.parenthesisCloseSet[parenthesisType]:
+ raise Exception("No closing brace")
+ self.moveNext()
+ if parenthesisType == 1: # [ : Get content
+ value = self.getContent(value)
+ elif parenthesisType == 2: # { : To address
+ value = self.toAddress(value)
+ elif parenthesisType == 3: # < : To offset
+ value = self.toOffset(value)
+ return value
+ else:
+ return self.parseSingleOp()
+
+ #
+ # Parse symbol of Multiplier(*)
+ #
+ # retval value or self.parseSingleOp()
+ #
+ def parseMul(self):
+ values = [self.parseBrace()]
+ while True:
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '*':
+ self.moveNext()
+ values.append(self.parseBrace())
+ else:
+ break
+ value = 1
+ for each in values:
+ value *= each
+ return value
+
+ #
+ # Parse symbol of And(&) and Or(|)
+ #
+ # retval value
+ #
+ def parseAndOr(self):
+ value = self.parseMul()
+ op = None
+ while True:
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '&':
+ self.moveNext()
+ value &= self.parseMul()
+ elif char == '|':
+ div_index = self.index
+ self.moveNext()
+ value |= self.parseMul()
+ else:
+ break
+
+ return value
+
+ #
+ # Parse symbol of Add(+) and Minus(-)
+ #
+ # retval sum(values)
+ #
+ def parseAddMinus(self):
+ values = [self.parseAndOr()]
+ while True:
+ self.skipSpace()
+ char = self.getCurr()
+ if char == '+':
+ self.moveNext()
+ values.append(self.parseAndOr())
+ elif char == '-':
+ self.moveNext()
+ values.append(-1 * self.parseAndOr())
+ else:
+ break
+ return sum(values)
+
+ #
+ # Parse expression
+ #
+ # retval self.parseAddMinus()
+ #
+ def parseExpr(self):
+ return self.parseAddMinus()
+
+ #
+ # Get result
+ #
+ # retval value
+ #
+ def getResult(self):
+ value = self.parseExpr()
+ self.skipSpace()
+ if not self.isLast():
+ raise Exception("Unexpected character found '%s'" % self.getCurr())
+ return value
+
+ #
+ # Get module GUID
+ #
+ # retval value
+ #
+ def getModGuid(self, var):
+ guid = (guid for guid,name in self.dictGuidNameXref.items() if name==var)
+ try:
+ value = guid.next()
+ except Exception:
+ raise Exception("Unknown module name %s !" % var)
+ return value
+
+ #
+ # Get variable
+ #
+ # retval value
+ #
+ def getVariable(self, var):
+ value = self.dictVariable.get(var, None)
+ if value == None:
+ raise Exception("Unrecognized variable '%s'" % var)
+ return value
+
+ #
+ # Get number
+ #
+ # retval value
+ #
+ def getNumber(self, var):
+ var = var.strip()
+ if var.startswith('0x'): # HEX
+ value = int(var, 16)
+ else:
+ value = int(var, 10)
+ return value
+
+ #
+ # Get content
+ #
+ # param [in] value
+ #
+ # retval value
+ #
+ def getContent(self, value):
+ return readDataFromFile (self.fdFile, self.toOffset(value), 4)
+
+ #
+ # Change value to address
+ #
+ # param [in] value
+ #
+ # retval value
+ #
+ def toAddress(self, value):
+ if value < self.fdSize:
+ value = value + self.fdBase
+ return value
+
+ #
+ # Change value to offset
+ #
+ # param [in] value
+ #
+ # retval value
+ #
+ def toOffset(self, value):
+ offset = None
+ for fvInfo in self.fvList:
+ if (value >= fvInfo['Base']) and (value < fvInfo['Base'] + fvInfo['Size']):
+ offset = value - fvInfo['Base'] + fvInfo['Offset']
+ if not offset:
+ if (value >= self.fdBase) and (value < self.fdBase + self.fdSize):
+ offset = value - self.fdBase
+ else:
+ offset = value
+ if offset >= self.fdSize:
+ raise Exception("Invalid file offset 0x%08x !" % value)
+ return offset
+
+ #
+ # Get GUID offset
+ #
+ # param [in] value
+ #
+ # retval value
+ #
+ def getGuidOff(self, value):
+ # GUID:Offset
+ symbolName = value.split(':')
+ if len(symbolName) == 3:
+ fvName = symbolName[0].upper()
+ keyName = '%s:%s' % (fvName, symbolName[1])
+ offStr = symbolName[2]
+ elif len(symbolName) == 2:
+ keyName = symbolName[0]
+ offStr = symbolName[1]
+ if keyName in self.dictFfsOffset:
+ value = (int(self.dictFfsOffset[keyName], 16) + int(offStr, 16)) & 0xFFFFFFFF
+ else:
+ raise Exception("Unknown GUID %s !" % value)
+ return value
+
+ #
+ # Get symbols
+ #
+ # param [in] value
+ #
+ # retval ret
+ #
+ def getSymbols(self, value):
+ if value in self.dictSymbolAddress:
+ # Module:Function
+ ret = int (self.dictSymbolAddress[value], 16)
+ else:
+ raise Exception("Unknown symbol %s !" % value)
+ return ret
+
+ #
+ # Evaluate symbols
+ #
+ # param [in] expression
+ # param [in] isOffset
+ #
+ # retval value & 0xFFFFFFFF
+ #
+ def evaluate(self, expression, isOffset):
+ self.index = 0
+ self.synUsed = False
+ self.string = expression
+ value = self.getResult()
+ if isOffset:
+ if self.synUsed:
+ # Consider it as an address first
+ value = self.toOffset(value)
+ if value & 0x80000000:
+ # Consider it as a negative offset next
+ offset = (~value & 0xFFFFFFFF) + 1
+ if offset < self.fdSize:
+ value = self.fdSize - offset
+ if value >= self.fdSize:
+ raise Exception("Invalid offset expression !")
+ return value & 0xFFFFFFFF
+
+#
+# Print out the usage
+#
+def Usage():
+ print ("PatchFv Version 0.50")
+ print ("Usage: \n\tPatchFv FvBuildDir [FvFileBaseNames:]FdFileBaseNameToPatch \"Offset, Value\"")
+
+def main():
+ #
+ # Parse the options and args
+ #
+ symTables = Symbols()
+
+ #
+ # If the arguments are less than 4, then return an error.
+ #
+ if len(sys.argv) < 4:
+ Usage()
+ return 1
+
+ #
+ # If it fails to create dictionaries, then return an error.
+ #
+ if symTables.createDicts(sys.argv[1], sys.argv[2]) != 0:
+ print ("ERROR: Failed to create symbol dictionary!!")
+ return 2
+
+ #
+ # Get FD file and size
+ #
+ fdFile = symTables.getFdFile()
+ fdSize = symTables.getFdSize()
+
+ try:
+ #
+ # Check to see if FSP header is valid
+ #
+ ret = IsFspHeaderValid(fdFile)
+ if ret == False:
+ raise Exception ("The FSP header is not valid. Stop patching FD.")
+ comment = ""
+ for fvFile in sys.argv[3:]:
+ #
+ # Check to see if it has enough arguments
+ #
+ items = fvFile.split(",")
+ if len (items) < 2:
+ raise Exception("Expect more arguments for '%s'!" % fvFile)
+
+ comment = ""
+ command = ""
+ params = []
+ for item in items:
+ item = item.strip()
+ if item.startswith("@"):
+ comment = item[1:]
+ elif item.startswith("$"):
+ command = item[1:]
+ else:
+ if len(params) == 0:
+ isOffset = True
+ else :
+ isOffset = False
+ #
+ # Parse symbols then append it to params
+ #
+ params.append (symTables.evaluate(item, isOffset))
+
+ #
+ # Patch a new value into FD file if it is not a command
+ #
+ if command == "":
+ # Patch a DWORD
+ if len (params) == 2:
+ offset = params[0]
+ value = params[1]
+ oldvalue = readDataFromFile(fdFile, offset, 4)
+ ret = patchDataInFile (fdFile, offset, value, 4) - 4
+ else:
+ raise Exception ("Patch command needs 2 parameters !")
+
+ if ret:
+ raise Exception ("Patch failed for offset 0x%08X" % offset)
+ else:
+ print ("Patched offset 0x%08X:[%08X] with value 0x%08X # %s" % (offset, oldvalue, value, comment))
+
+ elif command == "COPY":
+ #
+ # Copy binary block from source to destination
+ #
+ if len (params) == 3:
+ src = symTables.toOffset(params[0])
+ dest = symTables.toOffset(params[1])
+ clen = symTables.toOffset(params[2])
+ if (dest + clen <= fdSize) and (src + clen <= fdSize):
+ oldvalue = readDataFromFile(fdFile, src, clen)
+ ret = patchDataInFile (fdFile, dest, oldvalue, clen) - clen
+ else:
+ raise Exception ("Copy command OFFSET or LENGTH parameter is invalid !")
+ else:
+ raise Exception ("Copy command needs 3 parameters !")
+
+ if ret:
+ raise Exception ("Copy failed from offset 0x%08X to offset 0x%08X!" % (src, dest))
+ else :
+ print ("Copied %d bytes from offset 0x%08X ~ offset 0x%08X # %s" % (clen, src, dest, comment))
+ else:
+ raise Exception ("Unknown command %s!" % command)
+ return 0
+
+ except Exception as ex:
+ print ("ERROR: %s" % ex)
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/SplitFspBin.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/SplitFspBin.py
new file mode 100755
index 00000000..fe90f90b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/SplitFspBin.py
@@ -0,0 +1,892 @@
+## @ FspTool.py
+#
+# Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+import os
+import sys
+import uuid
+import copy
+import struct
+import argparse
+from ctypes import *
+from functools import reduce
+
+"""
+This utility supports some operations for Intel FSP 1.x/2.x image.
+It supports:
+ - Display FSP 1.x/2.x information header
+ - Split FSP 2.x image into individual FSP-T/M/S/O component
+ - Rebase FSP 1.x/2.x components to a different base address
+ - Generate FSP 1.x/2.x mapping C header file
+"""
+
+CopyRightHeaderFile = """/*
+ *
+ * Automatically generated file; DO NOT EDIT.
+ * FSP mapping file
+ *
+ */
+"""
+
+class c_uint24(Structure):
+ """Little-Endian 24-bit Unsigned Integer"""
+ _pack_ = 1
+ _fields_ = [('Data', (c_uint8 * 3))]
+
+ def __init__(self, val=0):
+ self.set_value(val)
+
+ def __str__(self, indent=0):
+ return '0x%.6x' % self.value
+
+ def __int__(self):
+ return self.get_value()
+
+ def set_value(self, val):
+ self.Data[0:3] = Val2Bytes(val, 3)
+
+ def get_value(self):
+ return Bytes2Val(self.Data[0:3])
+
+ value = property(get_value, set_value)
+
+class EFI_FIRMWARE_VOLUME_HEADER(Structure):
+ _fields_ = [
+ ('ZeroVector', ARRAY(c_uint8, 16)),
+ ('FileSystemGuid', ARRAY(c_uint8, 16)),
+ ('FvLength', c_uint64),
+ ('Signature', ARRAY(c_char, 4)),
+ ('Attributes', c_uint32),
+ ('HeaderLength', c_uint16),
+ ('Checksum', c_uint16),
+ ('ExtHeaderOffset', c_uint16),
+ ('Reserved', c_uint8),
+ ('Revision', c_uint8)
+ ]
+
+class EFI_FIRMWARE_VOLUME_EXT_HEADER(Structure):
+ _fields_ = [
+ ('FvName', ARRAY(c_uint8, 16)),
+ ('ExtHeaderSize', c_uint32)
+ ]
+
+class EFI_FFS_INTEGRITY_CHECK(Structure):
+ _fields_ = [
+ ('Header', c_uint8),
+ ('File', c_uint8)
+ ]
+
+class EFI_FFS_FILE_HEADER(Structure):
+ _fields_ = [
+ ('Name', ARRAY(c_uint8, 16)),
+ ('IntegrityCheck', EFI_FFS_INTEGRITY_CHECK),
+ ('Type', c_uint8),
+ ('Attributes', c_uint8),
+ ('Size', c_uint24),
+ ('State', c_uint8)
+ ]
+
+class EFI_COMMON_SECTION_HEADER(Structure):
+ _fields_ = [
+ ('Size', c_uint24),
+ ('Type', c_uint8)
+ ]
+
+class FSP_COMMON_HEADER(Structure):
+ _fields_ = [
+ ('Signature', ARRAY(c_char, 4)),
+ ('HeaderLength', c_uint32)
+ ]
+
+class FSP_INFORMATION_HEADER(Structure):
+ _fields_ = [
+ ('Signature', ARRAY(c_char, 4)),
+ ('HeaderLength', c_uint32),
+ ('Reserved1', c_uint16),
+ ('SpecVersion', c_uint8),
+ ('HeaderRevision', c_uint8),
+ ('ImageRevision', c_uint32),
+ ('ImageId', ARRAY(c_char, 8)),
+ ('ImageSize', c_uint32),
+ ('ImageBase', c_uint32),
+ ('ImageAttribute', c_uint16),
+ ('ComponentAttribute', c_uint16),
+ ('CfgRegionOffset', c_uint32),
+ ('CfgRegionSize', c_uint32),
+ ('Reserved2', c_uint32),
+ ('TempRamInitEntryOffset', c_uint32),
+ ('Reserved3', c_uint32),
+ ('NotifyPhaseEntryOffset', c_uint32),
+ ('FspMemoryInitEntryOffset', c_uint32),
+ ('TempRamExitEntryOffset', c_uint32),
+ ('FspSiliconInitEntryOffset', c_uint32)
+ ]
+
+class FSP_PATCH_TABLE(Structure):
+ _fields_ = [
+ ('Signature', ARRAY(c_char, 4)),
+ ('HeaderLength', c_uint16),
+ ('HeaderRevision', c_uint8),
+ ('Reserved', c_uint8),
+ ('PatchEntryNum', c_uint32)
+ ]
+
+class EFI_IMAGE_DATA_DIRECTORY(Structure):
+ _fields_ = [
+ ('VirtualAddress', c_uint32),
+ ('Size', c_uint32)
+ ]
+
+class EFI_TE_IMAGE_HEADER(Structure):
+ _fields_ = [
+ ('Signature', ARRAY(c_char, 2)),
+ ('Machine', c_uint16),
+ ('NumberOfSections', c_uint8),
+ ('Subsystem', c_uint8),
+ ('StrippedSize', c_uint16),
+ ('AddressOfEntryPoint', c_uint32),
+ ('BaseOfCode', c_uint32),
+ ('ImageBase', c_uint64),
+ ('DataDirectoryBaseReloc', EFI_IMAGE_DATA_DIRECTORY),
+ ('DataDirectoryDebug', EFI_IMAGE_DATA_DIRECTORY)
+ ]
+
+class EFI_IMAGE_DOS_HEADER(Structure):
+ _fields_ = [
+ ('e_magic', c_uint16),
+ ('e_cblp', c_uint16),
+ ('e_cp', c_uint16),
+ ('e_crlc', c_uint16),
+ ('e_cparhdr', c_uint16),
+ ('e_minalloc', c_uint16),
+ ('e_maxalloc', c_uint16),
+ ('e_ss', c_uint16),
+ ('e_sp', c_uint16),
+ ('e_csum', c_uint16),
+ ('e_ip', c_uint16),
+ ('e_cs', c_uint16),
+ ('e_lfarlc', c_uint16),
+ ('e_ovno', c_uint16),
+ ('e_res', ARRAY(c_uint16, 4)),
+ ('e_oemid', c_uint16),
+ ('e_oeminfo', c_uint16),
+ ('e_res2', ARRAY(c_uint16, 10)),
+ ('e_lfanew', c_uint16)
+ ]
+
+class EFI_IMAGE_FILE_HEADER(Structure):
+ _fields_ = [
+ ('Machine', c_uint16),
+ ('NumberOfSections', c_uint16),
+ ('TimeDateStamp', c_uint32),
+ ('PointerToSymbolTable', c_uint32),
+ ('NumberOfSymbols', c_uint32),
+ ('SizeOfOptionalHeader', c_uint16),
+ ('Characteristics', c_uint16)
+ ]
+
+class PE_RELOC_BLOCK_HEADER(Structure):
+ _fields_ = [
+ ('PageRVA', c_uint32),
+ ('BlockSize', c_uint32)
+ ]
+
+class EFI_IMAGE_OPTIONAL_HEADER32(Structure):
+ _fields_ = [
+ ('Magic', c_uint16),
+ ('MajorLinkerVersion', c_uint8),
+ ('MinorLinkerVersion', c_uint8),
+ ('SizeOfCode', c_uint32),
+ ('SizeOfInitializedData', c_uint32),
+ ('SizeOfUninitializedData', c_uint32),
+ ('AddressOfEntryPoint', c_uint32),
+ ('BaseOfCode', c_uint32),
+ ('BaseOfData', c_uint32),
+ ('ImageBase', c_uint32),
+ ('SectionAlignment', c_uint32),
+ ('FileAlignment', c_uint32),
+ ('MajorOperatingSystemVersion', c_uint16),
+ ('MinorOperatingSystemVersion', c_uint16),
+ ('MajorImageVersion', c_uint16),
+ ('MinorImageVersion', c_uint16),
+ ('MajorSubsystemVersion', c_uint16),
+ ('MinorSubsystemVersion', c_uint16),
+ ('Win32VersionValue', c_uint32),
+ ('SizeOfImage', c_uint32),
+ ('SizeOfHeaders', c_uint32),
+ ('CheckSum' , c_uint32),
+ ('Subsystem', c_uint16),
+ ('DllCharacteristics', c_uint16),
+ ('SizeOfStackReserve', c_uint32),
+ ('SizeOfStackCommit' , c_uint32),
+ ('SizeOfHeapReserve', c_uint32),
+ ('SizeOfHeapCommit' , c_uint32),
+ ('LoaderFlags' , c_uint32),
+ ('NumberOfRvaAndSizes', c_uint32),
+ ('DataDirectory', ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))
+ ]
+
+class EFI_IMAGE_OPTIONAL_HEADER32_PLUS(Structure):
+ _fields_ = [
+ ('Magic', c_uint16),
+ ('MajorLinkerVersion', c_uint8),
+ ('MinorLinkerVersion', c_uint8),
+ ('SizeOfCode', c_uint32),
+ ('SizeOfInitializedData', c_uint32),
+ ('SizeOfUninitializedData', c_uint32),
+ ('AddressOfEntryPoint', c_uint32),
+ ('BaseOfCode', c_uint32),
+ ('ImageBase', c_uint64),
+ ('SectionAlignment', c_uint32),
+ ('FileAlignment', c_uint32),
+ ('MajorOperatingSystemVersion', c_uint16),
+ ('MinorOperatingSystemVersion', c_uint16),
+ ('MajorImageVersion', c_uint16),
+ ('MinorImageVersion', c_uint16),
+ ('MajorSubsystemVersion', c_uint16),
+ ('MinorSubsystemVersion', c_uint16),
+ ('Win32VersionValue', c_uint32),
+ ('SizeOfImage', c_uint32),
+ ('SizeOfHeaders', c_uint32),
+ ('CheckSum' , c_uint32),
+ ('Subsystem', c_uint16),
+ ('DllCharacteristics', c_uint16),
+ ('SizeOfStackReserve', c_uint64),
+ ('SizeOfStackCommit' , c_uint64),
+ ('SizeOfHeapReserve', c_uint64),
+ ('SizeOfHeapCommit' , c_uint64),
+ ('LoaderFlags' , c_uint32),
+ ('NumberOfRvaAndSizes', c_uint32),
+ ('DataDirectory', ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))
+ ]
+
+class EFI_IMAGE_OPTIONAL_HEADER(Union):
+ _fields_ = [
+ ('PeOptHdr', EFI_IMAGE_OPTIONAL_HEADER32),
+ ('PePlusOptHdr', EFI_IMAGE_OPTIONAL_HEADER32_PLUS)
+ ]
+
+class EFI_IMAGE_NT_HEADERS32(Structure):
+ _fields_ = [
+ ('Signature', c_uint32),
+ ('FileHeader', EFI_IMAGE_FILE_HEADER),
+ ('OptionalHeader', EFI_IMAGE_OPTIONAL_HEADER)
+ ]
+
+
+class EFI_IMAGE_DIRECTORY_ENTRY:
+ EXPORT = 0
+ IMPORT = 1
+ RESOURCE = 2
+ EXCEPTION = 3
+ SECURITY = 4
+ BASERELOC = 5
+ DEBUG = 6
+ COPYRIGHT = 7
+ GLOBALPTR = 8
+ TLS = 9
+ LOAD_CONFIG = 10
+
+class EFI_FV_FILETYPE:
+ ALL = 0x00
+ RAW = 0x01
+ FREEFORM = 0x02
+ SECURITY_CORE = 0x03
+ PEI_CORE = 0x04
+ DXE_CORE = 0x05
+ PEIM = 0x06
+ DRIVER = 0x07
+ COMBINED_PEIM_DRIVER = 0x08
+ APPLICATION = 0x09
+ SMM = 0x0a
+ FIRMWARE_VOLUME_IMAGE = 0x0b
+ COMBINED_SMM_DXE = 0x0c
+ SMM_CORE = 0x0d
+ OEM_MIN = 0xc0
+ OEM_MAX = 0xdf
+ DEBUG_MIN = 0xe0
+ DEBUG_MAX = 0xef
+ FFS_MIN = 0xf0
+ FFS_MAX = 0xff
+ FFS_PAD = 0xf0
+
+class EFI_SECTION_TYPE:
+ """Enumeration of all valid firmware file section types."""
+ ALL = 0x00
+ COMPRESSION = 0x01
+ GUID_DEFINED = 0x02
+ DISPOSABLE = 0x03
+ PE32 = 0x10
+ PIC = 0x11
+ TE = 0x12
+ DXE_DEPEX = 0x13
+ VERSION = 0x14
+ USER_INTERFACE = 0x15
+ COMPATIBILITY16 = 0x16
+ FIRMWARE_VOLUME_IMAGE = 0x17
+ FREEFORM_SUBTYPE_GUID = 0x18
+ RAW = 0x19
+ PEI_DEPEX = 0x1b
+ SMM_DEPEX = 0x1c
+
+def AlignPtr (offset, alignment = 8):
+ return (offset + alignment - 1) & ~(alignment - 1)
+
+def Bytes2Val (bytes):
+ return reduce(lambda x,y: (x<<8)|y, bytes[::-1] )
+
+def Val2Bytes (value, blen):
+ return [(value>>(i*8) & 0xff) for i in range(blen)]
+
+def IsIntegerType (val):
+ if sys.version_info[0] < 3:
+ if type(val) in (int, long):
+ return True
+ else:
+ if type(val) is int:
+ return True
+ return False
+
+def IsStrType (val):
+ if sys.version_info[0] < 3:
+ if type(val) is str:
+ return True
+ else:
+ if type(val) is bytes:
+ return True
+ return False
+
+def HandleNameStr (val):
+ if sys.version_info[0] < 3:
+ rep = "0x%X ('%s')" % (Bytes2Val (bytearray (val)), val)
+ else:
+ rep = "0x%X ('%s')" % (Bytes2Val (bytearray (val)), str (val, 'utf-8'))
+ return rep
+
+def OutputStruct (obj, indent = 0, plen = 0):
+ if indent:
+ body = ''
+ else:
+ body = (' ' * indent + '<%s>:\n') % obj.__class__.__name__
+
+ if plen == 0:
+ plen = sizeof(obj)
+
+ max_key_len = 26
+ pstr = (' ' * (indent + 1) + '{0:<%d} = {1}\n') % max_key_len
+
+ for field in obj._fields_:
+ key = field[0]
+ val = getattr(obj, key)
+ rep = ''
+ if not isinstance(val, c_uint24) and isinstance(val, Structure):
+ body += pstr.format(key, val.__class__.__name__)
+ body += OutputStruct (val, indent + 1)
+ plen -= sizeof(val)
+ else:
+ if IsStrType (val):
+ rep = HandleNameStr (val)
+ elif IsIntegerType (val):
+ rep = '0x%X' % val
+ elif isinstance(val, c_uint24):
+ rep = '0x%X' % val.get_value()
+ elif 'c_ubyte_Array' in str(type(val)):
+ if sizeof(val) == 16:
+ if sys.version_info[0] < 3:
+ rep = str(bytearray(val))
+ else:
+ rep = bytes(val)
+ rep = str(uuid.UUID(bytes_le = rep)).upper()
+ else:
+ res = ['0x%02X'%i for i in bytearray(val)]
+ rep = '[%s]' % (','.join(res))
+ else:
+ rep = str(val)
+ plen -= sizeof(field[1])
+ body += pstr.format(key, rep)
+ if plen <= 0:
+ break
+ return body
+
+class Section:
+ def __init__(self, offset, secdata):
+ self.SecHdr = EFI_COMMON_SECTION_HEADER.from_buffer (secdata, 0)
+ self.SecData = secdata[0:int(self.SecHdr.Size)]
+ self.Offset = offset
+
+class FirmwareFile:
+ def __init__(self, offset, filedata):
+ self.FfsHdr = EFI_FFS_FILE_HEADER.from_buffer (filedata, 0)
+ self.FfsData = filedata[0:int(self.FfsHdr.Size)]
+ self.Offset = offset
+ self.SecList = []
+
+ def ParseFfs(self):
+ ffssize = len(self.FfsData)
+ offset = sizeof(self.FfsHdr)
+ if self.FfsHdr.Name != '\xff' * 16:
+ while offset < (ffssize - sizeof (EFI_COMMON_SECTION_HEADER)):
+ sechdr = EFI_COMMON_SECTION_HEADER.from_buffer (self.FfsData, offset)
+ sec = Section (offset, self.FfsData[offset:offset + int(sechdr.Size)])
+ self.SecList.append(sec)
+ offset += int(sechdr.Size)
+ offset = AlignPtr(offset, 4)
+
+class FirmwareVolume:
+ def __init__(self, offset, fvdata):
+ self.FvHdr = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (fvdata, 0)
+ self.FvData = fvdata[0 : self.FvHdr.FvLength]
+ self.Offset = offset
+ if self.FvHdr.ExtHeaderOffset > 0:
+ self.FvExtHdr = EFI_FIRMWARE_VOLUME_EXT_HEADER.from_buffer (self.FvData, self.FvHdr.ExtHeaderOffset)
+ else:
+ self.FvExtHdr = None
+ self.FfsList = []
+
+ def ParseFv(self):
+ fvsize = len(self.FvData)
+ if self.FvExtHdr:
+ offset = self.FvHdr.ExtHeaderOffset + self.FvExtHdr.ExtHeaderSize
+ else:
+ offset = self.FvHdr.HeaderLength
+ offset = AlignPtr(offset)
+ while offset < (fvsize - sizeof (EFI_FFS_FILE_HEADER)):
+ ffshdr = EFI_FFS_FILE_HEADER.from_buffer (self.FvData, offset)
+ if (ffshdr.Name == '\xff' * 16) and (int(ffshdr.Size) == 0xFFFFFF):
+ offset = fvsize
+ else:
+ ffs = FirmwareFile (offset, self.FvData[offset:offset + int(ffshdr.Size)])
+ ffs.ParseFfs()
+ self.FfsList.append(ffs)
+ offset += int(ffshdr.Size)
+ offset = AlignPtr(offset)
+
+class FspImage:
+ def __init__(self, offset, fih, fihoff, patch):
+ self.Fih = fih
+ self.FihOffset = fihoff
+ self.Offset = offset
+ self.FvIdxList = []
+ self.Type = "XTMSXXXXOXXXXXXX"[(fih.ComponentAttribute >> 12) & 0x0F]
+ self.PatchList = patch
+ self.PatchList.append(fihoff + 0x1C)
+
+ def AppendFv(self, FvIdx):
+ self.FvIdxList.append(FvIdx)
+
+ def Patch(self, delta, fdbin):
+ count = 0
+ applied = 0
+ for idx, patch in enumerate(self.PatchList):
+ ptype = (patch>>24) & 0x0F
+ if ptype not in [0x00, 0x0F]:
+ raise Exception('ERROR: Invalid patch type %d !' % ptype)
+ if patch & 0x80000000:
+ patch = self.Fih.ImageSize - (0x1000000 - (patch & 0xFFFFFF))
+ else:
+ patch = patch & 0xFFFFFF
+ if (patch < self.Fih.ImageSize) and (patch + sizeof(c_uint32) <= self.Fih.ImageSize):
+ offset = patch + self.Offset
+ value = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)])
+ value += delta
+ fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, sizeof(c_uint32))
+ applied += 1
+ count += 1
+ # Don't count the FSP base address patch entry appended at the end
+ if count != 0:
+ count -= 1
+ applied -= 1
+ return (count, applied)
+
+class FirmwareDevice:
+ def __init__(self, offset, fdfile):
+ self.FvList = []
+ self.FspList = []
+ self.FdFile = fdfile
+ self.Offset = 0
+ hfsp = open (self.FdFile, 'rb')
+ self.FdData = bytearray(hfsp.read())
+ hfsp.close()
+
+ def ParseFd(self):
+ offset = 0
+ fdsize = len(self.FdData)
+ self.FvList = []
+ while offset < (fdsize - sizeof (EFI_FIRMWARE_VOLUME_HEADER)):
+ fvh = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (self.FdData, offset)
+ if b'_FVH' != fvh.Signature:
+ raise Exception("ERROR: Invalid FV header !")
+ fv = FirmwareVolume (offset, self.FdData[offset:offset + fvh.FvLength])
+ fv.ParseFv ()
+ self.FvList.append(fv)
+ offset += fv.FvHdr.FvLength
+
+ def CheckFsp (self):
+ if len(self.FspList) == 0:
+ return
+
+ fih = None
+ for fsp in self.FspList:
+ if not fih:
+ fih = fsp.Fih
+ else:
+ newfih = fsp.Fih
+ if (newfih.ImageId != fih.ImageId) or (newfih.ImageRevision != fih.ImageRevision):
+ raise Exception("ERROR: Inconsistent FSP ImageId or ImageRevision detected !")
+
+ def ParseFsp(self):
+ flen = 0
+ for idx, fv in enumerate(self.FvList):
+ # Check if this FV contains FSP header
+ if flen == 0:
+ if len(fv.FfsList) == 0:
+ continue
+ ffs = fv.FfsList[0]
+ if len(ffs.SecList) == 0:
+ continue
+ sec = ffs.SecList[0]
+ if sec.SecHdr.Type != EFI_SECTION_TYPE.RAW:
+ continue
+ fihoffset = ffs.Offset + sec.Offset + sizeof(sec.SecHdr)
+ fspoffset = fv.Offset
+ offset = fspoffset + fihoffset
+ fih = FSP_INFORMATION_HEADER.from_buffer (self.FdData, offset)
+ if b'FSPH' != fih.Signature:
+ continue
+
+ offset += fih.HeaderLength
+ offset = AlignPtr(offset, 4)
+ plist = []
+ while True:
+ fch = FSP_COMMON_HEADER.from_buffer (self.FdData, offset)
+ if b'FSPP' != fch.Signature:
+ offset += fch.HeaderLength
+ offset = AlignPtr(offset, 4)
+ else:
+ fspp = FSP_PATCH_TABLE.from_buffer (self.FdData, offset)
+ offset += sizeof(fspp)
+ pdata = (c_uint32 * fspp.PatchEntryNum).from_buffer(self.FdData, offset)
+ plist = list(pdata)
+ break
+
+ fsp = FspImage (fspoffset, fih, fihoffset, plist)
+ fsp.AppendFv (idx)
+ self.FspList.append(fsp)
+ flen = fsp.Fih.ImageSize - fv.FvHdr.FvLength
+ else:
+ fsp.AppendFv (idx)
+ flen -= fv.FvHdr.FvLength
+ if flen < 0:
+ raise Exception("ERROR: Incorrect FV size in image !")
+ self.CheckFsp ()
+
+class PeTeImage:
+ def __init__(self, offset, data):
+ self.Offset = offset
+ tehdr = EFI_TE_IMAGE_HEADER.from_buffer (data, 0)
+ if tehdr.Signature == b'VZ': # TE image
+ self.TeHdr = tehdr
+ elif tehdr.Signature == b'MZ': # PE image
+ self.TeHdr = None
+ self.DosHdr = EFI_IMAGE_DOS_HEADER.from_buffer (data, 0)
+ self.PeHdr = EFI_IMAGE_NT_HEADERS32.from_buffer (data, self.DosHdr.e_lfanew)
+ if self.PeHdr.Signature != 0x4550:
+ raise Exception("ERROR: Invalid PE32 header !")
+ if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x10b: # PE32 image
+ if self.PeHdr.FileHeader.SizeOfOptionalHeader < EFI_IMAGE_OPTIONAL_HEADER32.DataDirectory.offset:
+ raise Exception("ERROR: Unsupported PE32 image !")
+ if self.PeHdr.OptionalHeader.PeOptHdr.NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:
+ raise Exception("ERROR: No relocation information available !")
+ elif self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x20b: # PE32+ image
+ if self.PeHdr.FileHeader.SizeOfOptionalHeader < EFI_IMAGE_OPTIONAL_HEADER32_PLUS.DataDirectory.offset:
+ raise Exception("ERROR: Unsupported PE32+ image !")
+ if self.PeHdr.OptionalHeader.PePlusOptHdr.NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:
+ raise Exception("ERROR: No relocation information available !")
+ else:
+ raise Exception("ERROR: Invalid PE32 optional header !")
+ self.Offset = offset
+ self.Data = data
+ self.RelocList = []
+
+ def IsTeImage(self):
+ return self.TeHdr is not None
+
+ def ParseReloc(self):
+ if self.IsTeImage():
+ rsize = self.TeHdr.DataDirectoryBaseReloc.Size
+ roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + self.TeHdr.DataDirectoryBaseReloc.VirtualAddress
+ else:
+ # Assuming PE32 image type (self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x10b)
+ rsize = self.PeHdr.OptionalHeader.PeOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size
+ roffset = self.PeHdr.OptionalHeader.PeOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].VirtualAddress
+ if self.PeHdr.OptionalHeader.PePlusOptHdr.Magic == 0x20b: # PE32+ image
+ rsize = self.PeHdr.OptionalHeader.PePlusOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size
+ roffset = self.PeHdr.OptionalHeader.PePlusOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].VirtualAddress
+
+ alignment = 4
+ offset = roffset
+ while offset < roffset + rsize:
+ offset = AlignPtr(offset, 4)
+ blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.Data, offset)
+ offset += sizeof(blkhdr)
+ # Read relocation type,offset pairs
+ rlen = blkhdr.BlockSize - sizeof(PE_RELOC_BLOCK_HEADER)
+ rnum = int (rlen/sizeof(c_uint16))
+ rdata = (c_uint16 * rnum).from_buffer(self.Data, offset)
+ for each in rdata:
+ roff = each & 0xfff
+ rtype = each >> 12
+ if rtype == 0: # IMAGE_REL_BASED_ABSOLUTE:
+ continue
+ if ((rtype != 3) and (rtype != 10)): # IMAGE_REL_BASED_HIGHLOW and IMAGE_REL_BASED_DIR64
+ raise Exception("ERROR: Unsupported relocation type %d!" % rtype)
+ # Calculate the offset of the relocation
+ aoff = blkhdr.PageRVA + roff
+ if self.IsTeImage():
+ aoff += sizeof(self.TeHdr) - self.TeHdr.StrippedSize
+ self.RelocList.append((rtype, aoff))
+ offset += sizeof(rdata)
+
+ def Rebase(self, delta, fdbin):
+ count = 0
+ if delta == 0:
+ return count
+
+ for (rtype, roff) in self.RelocList:
+ if rtype == 3: # IMAGE_REL_BASED_HIGHLOW
+ offset = roff + self.Offset
+ value = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)])
+ value += delta
+ fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, sizeof(c_uint32))
+ count += 1
+ elif rtype == 10: # IMAGE_REL_BASED_DIR64
+ offset = roff + self.Offset
+ value = Bytes2Val(fdbin[offset:offset+sizeof(c_uint64)])
+ value += delta
+ fdbin[offset:offset+sizeof(c_uint64)] = Val2Bytes(value, sizeof(c_uint64))
+ count += 1
+ else:
+ raise Exception('ERROR: Unknown relocation type %d !' % rtype)
+
+ if self.IsTeImage():
+ offset = self.Offset + EFI_TE_IMAGE_HEADER.ImageBase.offset
+ size = EFI_TE_IMAGE_HEADER.ImageBase.size
+ else:
+ offset = self.Offset + self.DosHdr.e_lfanew
+ offset += EFI_IMAGE_NT_HEADERS32.OptionalHeader.offset
+ if self.PeHdr.OptionalHeader.PePlusOptHdr.Magic == 0x20b: # PE32+ image
+ offset += EFI_IMAGE_OPTIONAL_HEADER32_PLUS.ImageBase.offset
+ size = EFI_IMAGE_OPTIONAL_HEADER32_PLUS.ImageBase.size
+ else:
+ offset += EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.offset
+ size = EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.size
+
+ value = Bytes2Val(fdbin[offset:offset+size]) + delta
+ fdbin[offset:offset+size] = Val2Bytes(value, size)
+
+ return count
+
+def ShowFspInfo (fspfile):
+ fd = FirmwareDevice(0, fspfile)
+ fd.ParseFd ()
+ fd.ParseFsp ()
+
+ print ("\nFound the following %d Firmware Volumes in FSP binary:" % (len(fd.FvList)))
+ for idx, fv in enumerate(fd.FvList):
+ name = fv.FvExtHdr.FvName
+ if not name:
+ name = '\xff' * 16
+ else:
+ if sys.version_info[0] < 3:
+ name = str(bytearray(name))
+ else:
+ name = bytes(name)
+ guid = uuid.UUID(bytes_le = name)
+ print ("FV%d:" % idx)
+ print (" GUID : %s" % str(guid).upper())
+ print (" Offset : 0x%08X" % fv.Offset)
+ print (" Length : 0x%08X" % fv.FvHdr.FvLength)
+ print ("\n")
+
+ for fsp in fd.FspList:
+ fvlist = map(lambda x : 'FV%d' % x, fsp.FvIdxList)
+ print ("FSP_%s contains %s" % (fsp.Type, ','.join(fvlist)))
+ print ("%s" % (OutputStruct(fsp.Fih, 0, fsp.Fih.HeaderLength)))
+
+def GenFspHdr (fspfile, outdir, hfile):
+ fd = FirmwareDevice(0, fspfile)
+ fd.ParseFd ()
+ fd.ParseFsp ()
+
+ if not hfile:
+ hfile = os.path.splitext(os.path.basename(fspfile))[0] + '.h'
+ fspname, ext = os.path.splitext(os.path.basename(hfile))
+ filename = os.path.join(outdir, fspname + ext)
+ hfsp = open(filename, 'w')
+ hfsp.write ('%s\n\n' % CopyRightHeaderFile)
+
+ firstfv = True
+ for fsp in fd.FspList:
+ fih = fsp.Fih
+ if firstfv:
+ if sys.version_info[0] < 3:
+ hfsp.write("#define FSP_IMAGE_ID 0x%016X /* '%s' */\n" % (Bytes2Val(bytearray(fih.ImageId)), fih.ImageId))
+ else:
+ hfsp.write("#define FSP_IMAGE_ID 0x%016X /* '%s' */\n" % (Bytes2Val(bytearray(fih.ImageId)), str (fih.ImageId, 'utf-8')))
+ hfsp.write("#define FSP_IMAGE_REV 0x%08X \n\n" % fih.ImageRevision)
+ firstfv = False
+ fv = fd.FvList[fsp.FvIdxList[0]]
+ hfsp.write ('#define FSP%s_BASE 0x%08X\n' % (fsp.Type, fih.ImageBase))
+ hfsp.write ('#define FSP%s_OFFSET 0x%08X\n' % (fsp.Type, fv.Offset))
+ hfsp.write ('#define FSP%s_LENGTH 0x%08X\n\n' % (fsp.Type, fih.ImageSize))
+
+ hfsp.close()
+
+def SplitFspBin (fspfile, outdir, nametemplate):
+ fd = FirmwareDevice(0, fspfile)
+ fd.ParseFd ()
+ fd.ParseFsp ()
+
+ for fsp in fd.FspList:
+ if fsp.Fih.HeaderRevision < 3:
+ raise Exception("ERROR: FSP 1.x is not supported by the split command !")
+ ftype = fsp.Type
+ if not nametemplate:
+ nametemplate = fspfile
+ fspname, ext = os.path.splitext(os.path.basename(nametemplate))
+ filename = os.path.join(outdir, fspname + '_' + fsp.Type + ext)
+ hfsp = open(filename, 'wb')
+ print ("Create FSP component file '%s'" % filename)
+ for fvidx in fsp.FvIdxList:
+ fv = fd.FvList[fvidx]
+ hfsp.write(fv.FvData)
+ hfsp.close()
+
+def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
+ fd = FirmwareDevice(0, FspBinary)
+ fd.ParseFd ()
+ fd.ParseFsp ()
+
+ numcomp = len(FspComponent)
+ baselist = FspBase
+ if numcomp != len(baselist):
+ print ("ERROR: Required number of base does not match number of FSP component !")
+ return
+
+ newfspbin = fd.FdData[:]
+
+ for idx, fspcomp in enumerate(FspComponent):
+
+ found = False
+ for fsp in fd.FspList:
+ # Is this FSP 1.x single binary?
+ if fsp.Fih.HeaderRevision < 3:
+ found = True
+ ftype = 'X'
+ break
+ ftype = fsp.Type.lower()
+ if ftype == fspcomp:
+ found = True
+ break
+
+ if not found:
+ print ("ERROR: Could not find FSP_%c component to rebase !" % fspcomp.upper())
+ return
+
+ fspbase = baselist[idx]
+ if fspbase.startswith('0x'):
+ newbase = int(fspbase, 16)
+ else:
+ newbase = int(fspbase)
+ oldbase = fsp.Fih.ImageBase
+ delta = newbase - oldbase
+ print ("Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype.upper(),oldbase,newbase))
+
+ imglist = []
+ for fvidx in fsp.FvIdxList:
+ fv = fd.FvList[fvidx]
+ for ffs in fv.FfsList:
+ for sec in ffs.SecList:
+ if sec.SecHdr.Type in [EFI_SECTION_TYPE.TE, EFI_SECTION_TYPE.PE32]: # TE or PE32
+ offset = fd.Offset + fv.Offset + ffs.Offset + sec.Offset + sizeof(sec.SecHdr)
+ imglist.append ((offset, len(sec.SecData) - sizeof(sec.SecHdr)))
+
+ fcount = 0
+ pcount = 0
+ for (offset, length) in imglist:
+ img = PeTeImage(offset, fd.FdData[offset:offset + length])
+ img.ParseReloc()
+ pcount += img.Rebase(delta, newfspbin)
+ fcount += 1
+
+ print (" Patched %d entries in %d TE/PE32 images." % (pcount, fcount))
+
+ (count, applied) = fsp.Patch(delta, newfspbin)
+ print (" Patched %d entries using FSP patch table." % applied)
+ if count != applied:
+ print (" %d invalid entries are ignored !" % (count - applied))
+
+ if OutputFile == '':
+ filename = os.path.basename(FspBinary)
+ base, ext = os.path.splitext(filename)
+ OutputFile = base + "_%08X" % newbase + ext
+
+ fspname, ext = os.path.splitext(os.path.basename(OutputFile))
+ filename = os.path.join(OutputDir, fspname + ext)
+ fd = open(filename, "wb")
+ fd.write(newfspbin)
+ fd.close()
+
+def main ():
+ parser = argparse.ArgumentParser()
+ subparsers = parser.add_subparsers(title='commands', dest="which")
+
+ parser_rebase = subparsers.add_parser('rebase', help='rebase a FSP into a new base address')
+ parser_rebase.set_defaults(which='rebase')
+ parser_rebase.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True)
+ parser_rebase.add_argument('-c', '--fspcomp', choices=['t','m','s','o'], nargs='+', dest='FspComponent', type=str, help='FSP component to rebase', default = "['t']", required = True)
+ parser_rebase.add_argument('-b', '--newbase', dest='FspBase', nargs='+', type=str, help='Rebased FSP binary file name', default = '', required = True)
+ parser_rebase.add_argument('-o', '--outdir' , dest='OutputDir', type=str, help='Output directory path', default = '.')
+ parser_rebase.add_argument('-n', '--outfile', dest='OutputFile', type=str, help='Rebased FSP binary file name', default = '')
+
+ parser_split = subparsers.add_parser('split', help='split a FSP into multiple components')
+ parser_split.set_defaults(which='split')
+ parser_split.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True)
+ parser_split.add_argument('-o', '--outdir' , dest='OutputDir', type=str, help='Output directory path', default = '.')
+ parser_split.add_argument('-n', '--nametpl', dest='NameTemplate', type=str, help='Output name template', default = '')
+
+ parser_genhdr = subparsers.add_parser('genhdr', help='generate a header file for FSP binary')
+ parser_genhdr.set_defaults(which='genhdr')
+ parser_genhdr.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True)
+ parser_genhdr.add_argument('-o', '--outdir' , dest='OutputDir', type=str, help='Output directory path', default = '.')
+ parser_genhdr.add_argument('-n', '--hfile', dest='HFileName', type=str, help='Output header file name', default = '')
+
+ parser_info = subparsers.add_parser('info', help='display FSP information')
+ parser_info.set_defaults(which='info')
+ parser_info.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True)
+
+ args = parser.parse_args()
+ if args.which in ['rebase', 'split', 'genhdr', 'info']:
+ if not os.path.exists(args.FspBinary):
+ raise Exception ("ERROR: Could not locate FSP binary file '%s' !" % args.FspBinary)
+ if hasattr(args, 'OutputDir') and not os.path.exists(args.OutputDir):
+ raise Exception ("ERROR: Invalid output directory '%s' !" % args.OutputDir)
+
+ if args.which == 'rebase':
+ RebaseFspBin (args.FspBinary, args.FspComponent, args.FspBase, args.OutputDir, args.OutputFile)
+ elif args.which == 'split':
+ SplitFspBin (args.FspBinary, args.OutputDir, args.NameTemplate)
+ elif args.which == 'genhdr':
+ GenFspHdr (args.FspBinary, args.OutputDir, args.HFileName)
+ elif args.which == 'info':
+ ShowFspInfo (args.FspBinary)
+ else:
+ parser.print_help()
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h
new file mode 100644
index 00000000..cfc89e48
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h
@@ -0,0 +1,16 @@
+#ifndef __FSPUPD_H__
+#define __FSPUPD_H__
+
+#include <FspEas.h>
+
+#pragma pack(1)
+
+#define FSPT_UPD_SIGNATURE 0x545F4450554D4551 /* 'QEMUPD_T' */
+
+#define FSPM_UPD_SIGNATURE 0x4D5F4450554D4551 /* 'QEMUPD_M' */
+
+#define FSPS_UPD_SIGNATURE 0x535F4450554D4551 /* 'QEMUPD_S' */
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h
new file mode 100644
index 00000000..b88c9be0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h
@@ -0,0 +1,75 @@
+#ifndef __FSPMUPD_H__
+#define __FSPMUPD_H__
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+
+/** Fsp M Configuration
+**/
+typedef struct {
+
+/** Offset 0x00C8 - Debug Serial Port Base address
+ Debug serial port base address. This option will be used only when the 'Serial Port
+ Debug Device' option is set to 'External Device'. 0x00000000(Default).
+**/
+ UINT32 SerialDebugPortAddress;
+
+/** Offset 0x00CC - Debug Serial Port Type
+ 16550 compatible debug serial port resource type. NONE means no serial port support.
+ 0x02:MMIO(Default).
+ 0:NONE, 1:I/O, 2:MMIO
+**/
+ UINT8 SerialDebugPortType;
+
+/** Offset 0x00CD - Serial Port Debug Device
+ Select active serial port device for debug.For SOC UART devices,'Debug Serial Port
+ Base' options will be ignored. 0x02:SOC UART2(Default).
+ 0:SOC UART0, 1:SOC UART1, 2:SOC UART2, 3:External Device
+**/
+ UINT8 SerialDebugPortDevice;
+
+/** Offset 0x00CE - Debug Serial Port Stride Size
+ Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default).
+ 0:1, 2:4
+**/
+ UINT8 SerialDebugPortStrideSize;
+
+/** Offset 0x00CF
+**/
+ UINT8 UnusedUpdSpace2[1];
+
+/** Offset 0x00D0
+**/
+ UINT8 ReservedFspmUpd[4];
+} FSP_M_CONFIG;
+
+/** Fsp M UPD Configuration
+**/
+typedef struct {
+
+/** Offset 0x0000
+**/
+ FSP_UPD_HEADER FspUpdHeader;
+
+/** Offset 0x00A8
+**/
+ FSPM_ARCH_UPD FspmArchUpd;
+
+/** Offset 0x00C8
+**/
+ FSP_M_CONFIG FspmConfig;
+
+/** Offset 0x00D4
+**/
+ UINT8 UnusedUpdSpace3[2];
+
+/** Offset 0x00D6
+**/
+ UINT16 UpdTerminator;
+} FSPM_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h
new file mode 100644
index 00000000..e859d827
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h
@@ -0,0 +1,69 @@
+#ifndef __FSPSUPD_H__
+#define __FSPSUPD_H__
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+
+/** Fsp S Configuration
+**/
+typedef struct {
+
+/** Offset 0x0118 - BMP Logo Data Size
+ BMP logo data buffer size. 0x00000000(Default).
+**/
+ UINT32 LogoSize;
+
+/** Offset 0x011C - BMP Logo Data Pointer
+ BMP logo data pointer to a BMP format buffer. 0x00000000(Default).
+**/
+ UINT32 LogoPtr;
+
+/** Offset 0x0120 - Graphics Configuration Data Pointer
+ Graphics configuration data used for initialization. 0x00000000(Default).
+**/
+ UINT32 GraphicsConfigPtr;
+
+/** Offset 0x0124 - PCI GFX Temporary MMIO Base
+ PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default).
+**/
+ UINT32 PciTempResourceBase;
+
+/** Offset 0x0128
+**/
+ UINT8 UnusedUpdSpace1[3];
+
+/** Offset 0x012B
+**/
+ UINT8 ReservedFspsUpd;
+} FSP_S_CONFIG;
+
+/** Fsp S UPD Configuration
+**/
+typedef struct {
+
+/** Offset 0x0000
+**/
+ FSP_UPD_HEADER FspUpdHeader;
+
+/** Offset 0x00F8
+**/
+ FSPS_ARCH_UPD FspsArchUpd;
+
+/** Offset 0x0118
+**/
+ FSP_S_CONFIG FspsConfig;
+
+/** Offset 0x012C
+**/
+ UINT8 UnusedUpdSpace2[2];
+
+/** Offset 0x012E
+**/
+ UINT16 UpdTerminator;
+} FSPS_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h
new file mode 100644
index 00000000..979ac324
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h
@@ -0,0 +1,87 @@
+#ifndef __FSPTUPD_H__
+#define __FSPTUPD_H__
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+
+/** Fsp T Common UPD
+**/
+typedef struct {
+
+/** Offset 0x0040
+**/
+ UINT8 Revision;
+
+/** Offset 0x0041
+**/
+ UINT8 Reserved[3];
+
+/** Offset 0x0044
+**/
+ UINT32 MicrocodeRegionBase;
+
+/** Offset 0x0048
+**/
+ UINT32 MicrocodeRegionLength;
+
+/** Offset 0x004C
+**/
+ UINT32 CodeRegionBase;
+
+/** Offset 0x0050
+**/
+ UINT32 CodeRegionLength;
+
+/** Offset 0x0054
+**/
+ UINT8 Reserved1[12];
+} FSPT_COMMON_UPD;
+
+/** Fsp T Configuration
+**/
+typedef struct {
+
+/** Offset 0x0060 - Chicken bytes to test Hex config
+ This option shows how to present option for 4 bytes data
+**/
+ UINT32 ChickenBytes;
+
+/** Offset 0x0064
+**/
+ UINT8 ReservedFsptUpd1[28];
+} FSP_T_CONFIG;
+
+/** Fsp T UPD Configuration
+**/
+typedef struct {
+
+/** Offset 0x0000
+**/
+ FSP_UPD_HEADER FspUpdHeader;
+
+/** Offset 0x0020
+**/
+ FSPT_ARCH_UPD FsptArchUpd;
+
+/** Offset 0x0040
+**/
+ FSPT_COMMON_UPD FsptCommonUpd;
+
+/** Offset 0x0060
+**/
+ FSP_T_CONFIG FsptConfig;
+
+/** Offset 0x0080
+**/
+ UINT8 UnusedUpdSpace0[6];
+
+/** Offset 0x0086
+**/
+ UINT16 UpdTerminator;
+} FSPT_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf
new file mode 100644
index 00000000..c4a041dc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf
@@ -0,0 +1,88 @@
+GlobalDataDef
+ SKUID = 0, "DEFAULT"
+EndGlobalData
+
+
+StructDef
+
+ Find "QEMUPD_T"
+ $gQemuFspPkgTokenSpaceGuid_Revision 1 bytes $_DEFAULT_ = 0x01
+ Skip 87 bytes
+ $gQemuFspPkgTokenSpaceGuid_ChickenBytes 4 bytes $_DEFAULT_ = 0x00000000
+
+ Find "QEMUPD_M"
+ $gQemuFspPkgTokenSpaceGuid_Revision 1 bytes $_DEFAULT_ = 0x01
+ Skip 35 bytes
+ $gQemuFspPkgTokenSpaceGuid_StackBase 4 bytes $_DEFAULT_ = 0x00070000
+ $gQemuFspPkgTokenSpaceGuid_StackSize 4 bytes $_DEFAULT_ = 0x00010000
+ $gQemuFspPkgTokenSpaceGuid_BootLoaderTolumSize 4 bytes $_DEFAULT_ = 0x00000000
+ $gPlatformFspPkgTokenSpaceGuid_Bootmode 4 bytes $_DEFAULT_ = 0x00000000
+ Skip 8 bytes
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortAddress 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortType 1 bytes $_DEFAULT_ = 0x02
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice 1 bytes $_DEFAULT_ = 0x02
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize 1 bytes $_DEFAULT_ = 0x02
+
+ Find "QEMUPD_S"
+ $gQemuFspPkgTokenSpaceGuid_Revision 1 bytes $_DEFAULT_ = 0x01
+ Skip 55 bytes
+ $gQemuFspPkgTokenSpaceGuid_LogoSize 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_LogoPtr 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_GraphicsConfigPtr 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_PciTempResourceBase 4 bytes $_DEFAULT_ = 0x80000000
+
+EndStruct
+
+
+List &EN_DIS
+ Selection 0x1 , "Enabled"
+ Selection 0x0 , "Disabled"
+EndList
+
+List &gQemuFspPkgTokenSpaceGuid_SerialDebugPortType
+ Selection 0 , "NONE"
+ Selection 1 , "I/O"
+ Selection 2 , "MMIO"
+EndList
+
+List &gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice
+ Selection 0 , "SOC UART0"
+ Selection 1 , "SOC UART1"
+ Selection 2 , "SOC UART2"
+ Selection 3 , "External Device"
+EndList
+
+List &gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize
+ Selection 0 , "1"
+ Selection 2 , "4"
+EndList
+
+BeginInfoBlock
+ PPVer "0.1"
+ Description "QEMU Platform"
+EndInfoBlock
+
+Page "FSP T"
+ EditNum $gQemuFspPkgTokenSpaceGuid_ChickenBytes, "Chicken bytes to test Hex config", HEX,
+ Help "This option shows how to present option for 4 bytes data"
+ "Valid range: 0x00000000 ~ 0xFFFFFFFF"
+EndPage
+
+Page "FSP MemoryInit Settings"
+ EditNum $gQemuFspPkgTokenSpaceGuid_SerialDebugPortAddress, "Debug Serial Port Base address", HEX,
+ Help "Debug serial port base address. This option will be used only when the 'Serial Port Debug Device' option is set to 'External Device'. 0x00000000(Default)."
+ "Valid range: 0x00000000 ~ 0xFFFFFFFF"
+ Combo $gQemuFspPkgTokenSpaceGuid_SerialDebugPortType, "Debug Serial Port Type", &gQemuFspPkgTokenSpaceGuid_SerialDebugPortType,
+ Help "16550 compatible debug serial port resource type. NONE means no serial port support. 0x02:MMIO(Default)."
+ Combo $gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice, "Serial Port Debug Device", &gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice,
+ Help "Select active serial port device for debug.For SOC UART devices,'Debug Serial Port Base' options will be ignored. 0x02:SOC UART2(Default)."
+ Combo $gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize, "Debug Serial Port Stride Size", &gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize,
+ Help "Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default)."
+EndPage
+
+Page "FSP SiliconInit Settings"
+ EditNum $gQemuFspPkgTokenSpaceGuid_PciTempResourceBase, "PCI GFX Temporary MMIO Base", HEX,
+ Help "PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default)."
+ "Valid range: 0x80000000 ~ 0xDFFFFFFF"
+EndPage
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml
new file mode 100644
index 00000000..db0513f9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml
@@ -0,0 +1,267 @@
+variable:
+ PLATFORM_NAME : QemuFspPkg
+ PLATFORM_GUID : 1BEDB57A-7904-406e-8486-C89FC7FB39EE
+ PLATFORM_VERSION : 0.1
+ DSC_SPECIFICATION : 0x00010005
+ OUTPUT_DIRECTORY : Build/QemuFspPkg
+ SUPPORTED_ARCHITECTURES : IA32|X64
+ BUILD_TARGETS : DEBUG|RELEASE
+ SKUID_IDENTIFIER : DEFAULT
+ FLASH_DEFINITION : QemuFspPkg/QemuFspPkg.fdf
+ FSP_T_UPD_TOOL_GUID : 34686CA3-34F9-4901-B82A-BA630F0714C6
+ FSP_V_UPD_TOOL_GUID : 4E2F4725-734A-4399-BAF5-B4E16348EB2F
+ FSP_M_UPD_TOOL_GUID : 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
+ FSP_S_UPD_TOOL_GUID : CAE3605B-5B34-4C85-B3D7-27D54273C40F
+ FSP_T_UPD_FFS_GUID : 70BCF6A5-FFB1-47D8-B1AE-EFE5508E23EA
+ FSP_V_UPD_FFS_GUID : 0197EF5E-2FFC-4089-8E55-F70400B18146
+ FSP_M_UPD_FFS_GUID : D5B86AEA-6AF7-40D4-8014-982301BC3D89
+ FSP_S_UPD_FFS_GUID : E3CD9B18-998C-4F76-B65E-98B154E5446F
+ FSP_PACKAGE : QemuFspPkg
+ FSP_IMAGE_ID : 0x245053464D455124 # $QEMFSP$
+ FSP_IMAGE_REV : 0x00001010
+ CAR_BASE_ADDRESS : 0x00000000
+ CAR_REGION_SIZE : 0x00080000
+ CAR_BLD_REGION_SIZE : 0x00070000
+ CAR_FSP_REGION_SIZE : 0x00010000
+ FSP_ARCH : X64
+
+
+template:
+
+
+configs:
+ - $ACTION :
+ page : TMP::"FSP T", MEM::"FSP MemoryInit Settings", SIL::"FSP SiliconInit Settings"
+ - $ACTION :
+ find : QEMUPD_T
+ - FSPT_UPD :
+ - FSP_UPD_HEADER :
+ - Signature :
+ length : 0x08
+ value : 0x545F4450554D4551
+ - Revision :
+ name : FsptUpdRevision
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x17
+ value : {0x00}
+ - FSPT_ARCH_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - Length :
+ length : 0x04
+ value : 0x00000020
+ - FspDebugHandler :
+ length : 0x04
+ value : 0x00000000
+ - Reserved1 :
+ length : 0x14
+ value : {0x00}
+ - FSPT_COMMON_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - MicrocodeRegionBase :
+ length : 0x04
+ value : 0x00000000
+ - MicrocodeRegionLength :
+ length : 0x04
+ value : 0x00000000
+ - CodeRegionBase :
+ length : 0x04
+ value : 0x00000000
+ - CodeRegionLength :
+ length : 0x04
+ value : 0x00000000
+ - Reserved1 :
+ length : 0x0C
+ value : {0x00}
+ - FSP_T_CONFIG :
+ - $ACTION :
+ page : TMP
+ - ChickenBytes :
+ name : Chicken bytes to test Hex config
+ type : EditNum, HEX, (0x00000000,0xFFFFFFFF)
+ help : >
+ This option shows how to present option for 4 bytes data
+ length : 0x04
+ value : 0x00000000
+ - ReservedFsptUpd1 :
+ length : 0x1C
+ value : {0x00}
+ - UpdTerminator :
+ length : 0x02
+ value : 0x55AA
+ - $ACTION :
+ find : QEMUPD_M
+ - FSPM_UPD :
+ - FSP_UPD_HEADER :
+ - Signature :
+ length : 0x08
+ value : 0x4D5F4450554D4551
+ - Revision :
+ name : FspmUpdRevision
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x17
+ value : {0x00}
+ - FSPM_ARCH_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - NvsBufferPtr :
+ struct : VOID*
+ length : 0x04
+ value : 0x00000000
+ - StackBase :
+ struct : VOID*
+ name : StackBase
+ help : >
+ Stack base for FSP use. Default- 0xFEF16000
+ length : 0x04
+ value : $(CAR_BLD_REGION_SIZE)
+ - StackSize :
+ name : StackSize
+ help : >
+ To pass the stack size for FSP use. Bootloader can programmatically get the FSP requested StackSize by using the defaults in the FSP-M component. This is the minimum stack size expected by this revision of FSP. Default- 0x2A000
+ length : 0x04
+ value : $(CAR_FSP_REGION_SIZE)
+ - BootLoaderTolumSize :
+ name : BootLoaderTolumSize
+ help : >
+ To pass Bootloader Tolum size.
+ length : 0x04
+ value : 0x00000000
+ - Bootmode :
+ name : Bootmode
+ help : >
+ To maintain Bootmode details.
+ length : 0x04
+ value : 0x00000000
+ - Reserved1 :
+ length : 0x08
+ value : {0x00}
+ - FSP_M_CONFIG :
+ - $ACTION :
+ page : MEM
+ - SerialDebugPortAddress :
+ name : Debug Serial Port Base address
+ type : EditNum, HEX, (0x00000000,0xFFFFFFFF)
+ help : >
+ Debug serial port base address. This option will be used only when the 'Serial Port Debug Device'
+ option is set to 'External Device'. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - SerialDebugPortType :
+ name : Debug Serial Port Type
+ type : Combo
+ option : 0:NONE, 1:I/O, 2:MMIO
+ help : >
+ 16550 compatible debug serial port resource type. NONE means no serial port support. 0x02:MMIO(Default).
+ length : 0x01
+ value : 0x02
+ - SerialDebugPortDevice :
+ name : Serial Port Debug Device
+ type : Combo
+ option : 0:SOC UART0, 1:SOC UART1, 2:SOC UART2, 3:External Device
+ help : >
+ Select active serial port device for debug.
+ For SOC UART devices,'Debug Serial Port Base' options will be ignored. 0x02:SOC UART2(Default).
+ length : 0x01
+ value : 0x02
+ - SerialDebugPortStrideSize :
+ name : Debug Serial Port Stride Size
+ type : Combo
+ option : 0:1, 2:4
+ help : >
+ Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default).
+ length : 0x01
+ value : 0x02
+ - ReservedFspmUpd :
+ length : 0x04
+ value : {0x00}
+ - UpdTerminator :
+ length : 0x02
+ value : 0x55AA
+ - $ACTION :
+ find : QEMUPD_S
+ - FSPS_UPD :
+ - FSP_UPD_HEADER :
+ - Signature :
+ length : 0x08
+ value : 0x535F4450554D4551
+ - Revision :
+ name : FspsUpdRevision
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x17
+ value : {0x00}
+ - FSPS_ARCH_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - Length :
+ length : 0x04
+ value : 0x00000020
+ - FspEventHandler :
+ length : 0x04
+ value : 0x00000000
+ - EnableMultiPhaseSiliconInit :
+ length : 0x01
+ value : 0x00
+ - Reserved1 :
+ length : 0x13
+ value : {0x00}
+ - FSP_S_CONFIG :
+ - $ACTION :
+ page : SIL
+ - LogoSize :
+ name : BMP Logo Data Size
+ type : Reserved
+ help : >
+ BMP logo data buffer size. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - LogoPtr :
+ name : BMP Logo Data Pointer
+ type : Reserved
+ help : >
+ BMP logo data pointer to a BMP format buffer. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - GraphicsConfigPtr :
+ name : Graphics Configuration Data Pointer
+ type : Reserved
+ help : >
+ Graphics configuration data used for initialization. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - PciTempResourceBase :
+ name : PCI GFX Temporary MMIO Base
+ type : EditNum, HEX, (0x80000000,0xDFFFFFFF)
+ help : >
+ PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default).
+ length : 0x04
+ value : 0x80000000
+ - ReservedFspsUpd :
+ length : 0x01
+ value : 0x00
+ - UpdTerminator :
+ length : 0x02
+ value : 0x55AA
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc
new file mode 100644
index 00000000..25d51783
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc
@@ -0,0 +1,471 @@
+## @file
+# FSP DSC build file for QEMU platform
+#
+# Copyright (c) 2017 - 2021, 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 Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = QemuFspPkg
+ PLATFORM_GUID = 1BEDB57A-7904-406e-8486-C89FC7FB39EE
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/QemuFspPkg
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+ FLASH_DEFINITION = QemuFspPkg/QemuFspPkg.fdf
+
+ #
+ # UPD tool definition
+ #
+ FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
+ FSP_V_UPD_TOOL_GUID = 4E2F4725-734A-4399-BAF5-B4E16348EB2F
+ FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
+ FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
+ FSP_T_UPD_FFS_GUID = 70BCF6A5-FFB1-47D8-B1AE-EFE5508E23EA
+ FSP_V_UPD_FFS_GUID = 0197EF5E-2FFC-4089-8E55-F70400B18146
+ FSP_M_UPD_FFS_GUID = D5B86AEA-6AF7-40D4-8014-982301BC3D89
+ FSP_S_UPD_FFS_GUID = E3CD9B18-998C-4F76-B65E-98B154E5446F
+
+ #
+ # Set platform specific package/folder name, same as passed from PREBUILD script.
+ # PLATFORM_PACKAGE would be the same as PLATFORM_NAME as well as package build folder
+ # DEFINE only takes effect at R9 DSC and FDF.
+ #
+ DEFINE FSP_PACKAGE = QemuFspPkg
+ DEFINE FSP_IMAGE_ID = 0x245053464D455124 # $QEMFSP$
+ DEFINE FSP_IMAGE_REV = 0x00001010
+
+ DEFINE CAR_BASE_ADDRESS = 0x00000000
+ DEFINE CAR_REGION_SIZE = 0x00080000
+ DEFINE CAR_BLD_REGION_SIZE = 0x00070000
+ DEFINE CAR_FSP_REGION_SIZE = 0x00010000
+
+ DEFINE FSP_ARCH = X64
+
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this
+# Platform.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses]
+ PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+ CacheLib|IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf
+ CacheAsRamLib|IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf
+ FspSwitchStackLib|IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
+ FspCommonLib|IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
+ FspPlatformLib|IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
+ PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+!if $(TARGET) == DEBUG
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
+!endif
+
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+[PcdsFixedAtBuild]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot | TRUE
+ gQemuFspPkgTokenSpaceGuid.PcdFspHeaderRevision | 0x03
+ gQemuFspPkgTokenSpaceGuid.PcdFspImageIdString | $(FSP_IMAGE_ID)
+ gQemuFspPkgTokenSpaceGuid.PcdFspImageRevision | $(FSP_IMAGE_REV)
+ #
+ # FSP CAR Usages (BL RAM | FSP RAM | FSP CODE)
+ #
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase | $(CAR_BASE_ADDRESS)
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize | $(CAR_REGION_SIZE)
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize | $(CAR_FSP_REGION_SIZE)
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedBufferSize | 0x0100
+
+ # This defines how much space will be used for heap in FSP temporary memory
+ # x % of FSP temporary memory will be used for heap
+ # (100 - x) % of FSP temporary memory will be used for stack
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspHeapSizePercentage | 65
+
+ # This is a platform specific global pointer used by FSP
+ gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress | 0xFED00148
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedMemoryLength | 0x00100000
+
+!if $(TARGET) == RELEASE
+ gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel | 0x00000000
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel | 0x80000047
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0x27
+!endif
+
+[PcdsPatchableInModule]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress | 0xE0000000
+ #
+ # This entry will be patched during the build process
+ #
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress | 0x12345678
+
+!if $(TARGET) == RELEASE
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel | 0
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel | 0x80000047
+!endif
+
+[PcdsDynamicVpd.Upd]
+ #
+ # This section is not used by the normal build process
+ # However, FSP will use dedicated tool to handle it and generate a
+ # VPD similar binary block (User Configuration Data). This block will
+ # be accessed through a generated data structure directly rather than
+ # PCD services. This is for size consideration.
+ # Format:
+ # gQemuFspPkgTokenSpaceGuid.Updxxxxxxxxxxxxn | OFFSET | LENGTH | VALUE
+ # Only simple data type is supported
+ #
+
+ #
+ # Comments with !BSF will be used to generate BSF file
+ # Comments with !HDR will be used to generate H header file
+ #
+
+ # Global definitions in BSF
+ # !BSF PAGES:{TMP:"FSP T", MEM:"FSP MemoryInit Settings", SIL:"FSP SiliconInit Settings"}
+ # !BSF BLOCK:{NAME:"QEMU Platform", VER:"0.1"}
+
+ # !BSF FIND:{QEMUPD_T}
+ # !HDR COMMENT:{FSP_UPD_HEADER:FSP UPD Header}
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:START}
+ # FsptUpdSignature: {QEMUPD_T}
+ gQemuFspPkgTokenSpaceGuid.Signature | * | 0x08 | 0x545F4450554D4551
+ # !BSF NAME:{FsptUpdRevision}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x17 | {0x00}
+
+ # !HDR COMMENT:{FSPT_ARCH_UPD:FSPT_ARCH_UPD}
+ # !HDR EMBED:{FSPT_ARCH_UPD:FsptArchUpd:START}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+ gQemuFspPkgTokenSpaceGuid.Length | * | 0x04 | 0x00000020
+ gQemuFspPkgTokenSpaceGuid.FspDebugHandler | * | 0x04 | 0x00000000
+ # !HDR EMBED:{FSPT_ARCH_UPD:FsptArchUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x14 | {0x00}
+
+ # !HDR COMMENT:{FSPT_COMMON_UPD:Fsp T Common UPD}
+ # !HDR EMBED:{FSPT_COMMON_UPD:FsptCommonUpd:START}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+
+ # Base address of the microcode region.
+ gQemuFspPkgTokenSpaceGuid.MicrocodeRegionBase | * | 0x04 | 0x00000000
+
+ # Length of the microcode region.
+ gQemuFspPkgTokenSpaceGuid.MicrocodeRegionLength | * | 0x04 | 0x00000000
+
+ # Base address of the cacheable flash region.
+ gQemuFspPkgTokenSpaceGuid.CodeRegionBase | * | 0x04 | 0x00000000
+
+ # Length of the cacheable flash region.
+ gQemuFspPkgTokenSpaceGuid.CodeRegionLength | * | 0x04 | 0x00000000
+
+ # !HDR EMBED:{FSPT_COMMON_UPD:FsptCommonUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x0C | {0x00}
+
+ # !HDR COMMENT:{FSP_T_CONFIG:Fsp T Configuration}
+ # !HDR EMBED:{FSP_T_CONFIG:FsptConfig:START}
+ # !BSF PAGE:{TMP}
+ # !BSF NAME:{Chicken bytes to test Hex config}
+ # !BSF TYPE:{EditNum, HEX, (0x00000000,0xFFFFFFFF)}
+ # !BSF HELP:{This option shows how to present option for 4 bytes data}
+ gQemuFspPkgTokenSpaceGuid.ChickenBytes | * | 0x04 | 0x00000000
+
+ # !HDR EMBED:{FSP_T_CONFIG:FsptConfig:END}
+ gQemuFspPkgTokenSpaceGuid.ReservedFsptUpd1 | * | 0x1C | {0x00}
+
+ # Note please keep "UpdTerminator" at the end of each UPD region.
+ # The tool will use this field to determine the actual end of the UPD data
+ # structure.
+ gQemuFspPkgTokenSpaceGuid.UpdTerminator | * | 0x02 | 0x55AA
+
+ ################################################################################
+ #
+ # UPDs consumed in FspMemoryInit Api
+ #
+ ################################################################################
+ # !BSF FIND:{QEMUPD_M}
+ # !HDR COMMENT:{FSP_UPD_HEADER:FSP UPD Header}
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:START}
+ # FspmUpdSignature: {QEMUPD_M}
+ gQemuFspPkgTokenSpaceGuid.Signature | * | 0x08 | 0x4D5F4450554D4551
+ # !BSF NAME:{FspmUpdRevision}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x17 | {0x00}
+
+ # !HDR COMMENT:{FSPM_ARCH_UPD:Fsp M Architectural UPD}
+ # !HDR EMBED:{FSPM_ARCH_UPD:FspmArchUpd:START}
+
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+
+ # !HDR STRUCT:{VOID*}
+ gQemuFspPkgTokenSpaceGuid.NvsBufferPtr | * | 0x04 | 0x00000000
+
+ # !HDR STRUCT:{VOID*}
+ # !BSF NAME:{StackBase}
+ # !BSF HELP:{Stack base for FSP use. Default: 0xFEF16000}
+ gQemuFspPkgTokenSpaceGuid.StackBase | * | 0x04 | $(CAR_BLD_REGION_SIZE)
+
+ # !BSF NAME:{StackSize}
+ # !BSF HELP:{To pass the stack size for FSP use. Bootloader can programmatically get the FSP requested StackSize by using the defaults in the FSP-M component. This is the minimum stack size expected by this revision of FSP. Default: 0x2A000}
+ gQemuFspPkgTokenSpaceGuid.StackSize | * | 0x04 | $(CAR_FSP_REGION_SIZE)
+
+ # !BSF NAME:{BootLoaderTolumSize}
+ # !BSF HELP:{To pass Bootloader Tolum size.}
+ gQemuFspPkgTokenSpaceGuid.BootLoaderTolumSize | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{Bootmode}
+ # !BSF HELP:{To maintain Bootmode details.}
+ gPlatformFspPkgTokenSpaceGuid.Bootmode | * | 0x04 | 0x00000000
+
+ # !HDR EMBED:{FSPM_ARCH_UPD:FspmArchUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x08 | {0x00}
+
+ # !HDR COMMENT:{FSP_M_CONFIG:Fsp M Configuration}
+ # !HDR EMBED:{FSP_M_CONFIG:FspmConfig:START}
+ # !BSF PAGE:{MEM}
+ # !BSF NAME:{Debug Serial Port Base address}
+ # !BSF TYPE:{EditNum, HEX, (0x00000000,0xFFFFFFFF)}
+ # !BSF HELP:{Debug serial port base address. This option will be used only when the 'Serial Port Debug Device'}
+ # !BSF HELP:{+ option is set to 'External Device'. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortAddress | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{Debug Serial Port Type} TYPE:{Combo}
+ # !BSF OPTION:{0:NONE, 1:I/O, 2:MMIO}
+ # !BSF HELP:{16550 compatible debug serial port resource type. NONE means no serial port support. 0x02:MMIO(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortType | * | 0x01 | 0x02
+
+ # !BSF NAME:{Serial Port Debug Device} TYPE:{Combo}
+ # !BSF OPTION:{0:SOC UART0, 1:SOC UART1, 2:SOC UART2, 3:External Device}
+ # !BSF HELP:{Select active serial port device for debug.}
+ # !BSF HELP:{+For SOC UART devices,'Debug Serial Port Base' options will be ignored. 0x02:SOC UART2(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortDevice | * | 0x01 | 0x02
+
+ # !BSF NAME:{Debug Serial Port Stride Size} TYPE:{Combo}
+ # !BSF OPTION:{0:1, 2:4}
+ # !BSF HELP:{Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortStrideSize | * | 0x01 | 0x02
+
+
+ # !HDR EMBED:{FSP_M_CONFIG:FspmConfig:END}
+ gQemuFspPkgTokenSpaceGuid.ReservedFspmUpd | * | 0x04 | {0x00}
+
+
+ # Note please keep "UpdTerminator" at the end of each UPD region.
+ # The tool will use this field to determine the actual end of the UPD data
+ # structure.
+ gQemuFspPkgTokenSpaceGuid.UpdTerminator | * | 0x02 | 0x55AA
+
+ ################################################################################
+ #
+ # UPDs consumed in FspSiliconInit Api
+ #
+ ################################################################################
+ # !BSF FIND:{QEMUPD_S}
+ # !HDR COMMENT:{FSP_UPD_HEADER:FSP UPD Header}
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:START}
+ # FspsUpdSignature: {QEMUPD_S}
+ gQemuFspPkgTokenSpaceGuid.Signature | * | 0x08 | 0x535F4450554D4551
+ # !BSF NAME:{FspsUpdRevision}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x17 | {0x00}
+
+ # !HDR COMMENT:{FSPS_ARCH_UPD:FSPS_ARCH_UPD}
+ # !HDR EMBED:{FSPS_ARCH_UPD:FspsArchUpd:START}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+ gQemuFspPkgTokenSpaceGuid.Length | * | 0x04 | 0x00000020
+ gQemuFspPkgTokenSpaceGuid.FspEventHandler | * | 0x04 | 0x00000000
+ gQemuFspPkgTokenSpaceGuid.EnableMultiPhaseSiliconInit | * | 0x01 | 0x00
+ # !HDR EMBED:{FSPS_ARCH_UPD:FspsArchUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x13 | {0x00}
+
+ # !HDR COMMENT:{FSP_S_CONFIG:Fsp S Configuration}
+ # !HDR EMBED:{FSP_S_CONFIG:FspsConfig:START}
+ # !BSF PAGE:{SIL}
+
+ # !BSF NAME:{BMP Logo Data Size}
+ # !BSF TYPE:{Reserved}
+ # !BSF HELP:{BMP logo data buffer size. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.LogoSize | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{BMP Logo Data Pointer}
+ # !BSF TYPE:{Reserved}
+ # !BSF HELP:{BMP logo data pointer to a BMP format buffer. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.LogoPtr | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{Graphics Configuration Data Pointer}
+ # !BSF TYPE:{Reserved}
+ # !BSF HELP:{Graphics configuration data used for initialization. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.GraphicsConfigPtr | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{PCI GFX Temporary MMIO Base}
+ # !BSF TYPE:{EditNum, HEX, (0x80000000,0xDFFFFFFF)}
+ # !BSF HELP:{PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.PciTempResourceBase | * | 0x04 | 0x80000000
+
+ # !HDR EMBED:{FSP_S_CONFIG:FspsConfig:END}
+ gQemuFspPkgTokenSpaceGuid.ReservedFspsUpd | * | 0x01 | 0x00
+
+ # Note please keep "UpdTerminator" at the end of each UPD region.
+ # The tool will use this field to determine the actual end of the UPD data
+ # structure.
+ gQemuFspPkgTokenSpaceGuid.UpdTerminator | * | 0x02 | 0x55AA
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+# tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+# into firmware volume images. This section is just a list of modules to compile from
+# source into UEFI-compliant binaries.
+# It is the FDF file that contains information on combining binary files into firmware
+# volume images, whose concept is beyond UEFI and is described in PI specification.
+# Binary modules do not need to be listed in this section, as they should be
+# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
+# Logo (Logo.bmp), and etc.
+# There may also be modules listed in this section that are not required in the FDF file,
+# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+# generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
+[Components.IA32]
+ #
+ # FSP Binary Components
+ #
+ $(FSP_PACKAGE)/FspHeader/FspHeader.inf
+
+ #
+ # SEC
+ #
+ IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecTLib.inf
+ }
+
+[Components.$(FSP_ARCH)]
+ IntelFsp2Pkg/FspSecCore/FspSecCoreV.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecVLib.inf
+ }
+
+ IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecMLib.inf
+ }
+
+ IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecSLib.inf
+ }
+
+ #
+ # PEI Core
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+
+ #
+ # PCD
+ #
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+
+ $(FSP_PACKAGE)/FspvInit/FspvInit.inf
+ $(FSP_PACKAGE)/FspmInit/FspmInit.inf
+ $(FSP_PACKAGE)/FspsInit/FspsInit.inf
+ $(FSP_PACKAGE)/QemuVideo/QemuVideo.inf
+ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
+ <LibraryClasses>
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+ ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
+ }
+ IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf
+
+###################################################################################################
+#
+# BuildOptions Section - Define the module specific tool chain flags that should be used as
+# the default flags for a module. These flags are appended to any
+# standard flags that are defined by the build process. They can be
+# applied for any modules or only those modules with the specific
+# module style (EDK or EDKII) specified in [Components] section.
+#
+###################################################################################################
+[BuildOptions]
+# Append build options for EDK and EDKII drivers (= is Append, == is Replace)
+ # Enable link-time optimization when building with GCC49
+ *_GCC49_IA32_CC_FLAGS = -flto
+ *_GCC49_IA32_DLINK_FLAGS = -flto
+ *_GCC5_IA32_CC_FLAGS = -fno-pic
+ *_GCC5_IA32_DLINK_FLAGS = -no-pie
+ *_GCC5_IA32_ASLCC_FLAGS = -fno-pic
+ *_GCC5_IA32_ASLDLINK_FLAGS = -no-pie
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py
new file mode 100644
index 00000000..a71073ba
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py
@@ -0,0 +1,96 @@
+# @file
+# Split a file into two pieces at the request offset.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+# Import Modules
+import unittest
+import tempfile
+import os
+import shutil
+import struct as st
+import filecmp
+
+import os, sys
+currentdir = os.path.dirname(os.path.realpath(__file__))
+parentdir = os.path.dirname(currentdir)
+sys.path.append(parentdir)
+import FspDscBsf2Yaml
+
+YamlHeaderLineLength = 10
+HdrFileHeaderLineLength = 32
+BsfFileHeaderLineLength = 19
+
+def GenFileWithoutHdr(inputfile, numLineToStrip):
+ yaml_file = open(inputfile, "r")
+ lines = yaml_file.readlines()
+ yaml_file.close()
+ del lines[:numLineToStrip]
+
+ noHdrOutputFileName = "no-header-" + inputfile
+ stripped_file = open(noHdrOutputFileName, "w")
+ for line in lines:
+ stripped_file.write(line)
+ stripped_file.close()
+ return noHdrOutputFileName
+
+class TestFspScripts(unittest.TestCase):
+ def test_generateFspHeader_fromDsc(self):
+ # Generate HEADER
+ cmd = '{} {} HEADER {} {} {}'.format(
+ 'python',
+ '..\GenCfgOpt.py',
+ 'QemuFspPkg.dsc',
+ '.',
+ "")
+ os.system(cmd)
+ noHdrOutputFileName = GenFileWithoutHdr("FspUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFspUpd.h'))
+
+ def test_generateFspsHeader_fromDsc(self):
+ noHdrOutputFileName = GenFileWithoutHdr("FspsUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFspsUpd.h'))
+
+ def test_generateFsptHeader_fromDsc(self):
+ noHdrOutputFileName = GenFileWithoutHdr("FsptUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFsptUpd.h'))
+
+ def test_generateFspmHeader_fromDsc(self):
+ noHdrOutputFileName = GenFileWithoutHdr("FspmUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFspmUpd.h'))
+
+ def test_generateBsf_fromDsc(self):
+ # Generate BSF
+ cmd = '{} {} GENBSF {} {} {}'.format(
+ 'python',
+ '..\GenCfgOpt.py',
+ 'QemuFspPkg.dsc',
+ '.',
+ "Output.bsf")
+ os.system(cmd)
+ noHdrOutputFileName = GenFileWithoutHdr("Output.bsf", BsfFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedOutput.bsf'))
+
+ def test_generateYaml_fromDsc(self):
+ # Generate YAML
+ cmd = '{} {} {} {}'.format(
+ 'python',
+ '..\FspDscBsf2Yaml.py',
+ 'QemuFspPkg.dsc',
+ "Output.yaml")
+ os.system(cmd)
+ noHdrOutputFileName = GenFileWithoutHdr("Output.yaml", YamlHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedOutput.yaml'))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md
new file mode 100644
index 00000000..e739ffc2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md
@@ -0,0 +1,39 @@
+#Name
+**FspDscBsf2Yaml.py** The python script that generates YAML file for
+the Boot Settings from an EDK II Platform Description (**DSC**) file
+or from a Boot Settings File (**BSF**). It is created to help
+transitioning FSP Updateable Product Data (**UPD**) file format to
+new standardized YAML format so that it can be configured through
+open source tools.
+
+#Synopsis
+```
+FspDscBsf2Yaml DscFile|BsfFile YamlFile
+```
+
+#Description
+**FspDscBsf2Yaml.py** is a script that generates configuration options from an
+**EDK II Platform Description (DSC)** file or **a Boot Settings File (BSF)** file.
+
+It generates a **YAML file** that can be used by the **Config Editor** to provide
+a graphical user interface for manipulating settings in the UPD regions.
+
+The following sections explain the usage of this script.
+
+## 1. FspDscBsf2Yaml.py DscFile YamlFile
+
+The **DscFile** option is an input DSC file.
+
+The **YamlFile** option is an output YAML file.
+
+The script takes the FSP DSC file consisting BSF syntax and generates a YAML
+output file describing the boot settings.
+
+## 2. FspDscBsf2Yaml.py BsfFile YamlFile
+
+The **BsfFile** option is an input BSF file.
+
+The **YamlFile** option is an output YAML file.
+
+The script generates a YAML output file from a BSF file. The BSF file
+can be generated using GenCfgOpt tool.
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/GenCfgOptUserManual.md b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/GenCfgOptUserManual.md
new file mode 100644
index 00000000..53a42f94
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/GenCfgOptUserManual.md
@@ -0,0 +1,353 @@
+#Name
+**GenCfgOpt.py** The python script that generates UPD text (**.txt**) files for
+the compiler, header files for the UPD regions, and generates a Boot Settings
+File (**BSF**), all from an EDK II Platform Description (**DSC**) file.
+
+#Synopsis
+```
+GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [TxtOutFile] [-D Macros]
+GenCfgOpt HEADER PlatformDscFile BuildFvDir [InputHFile] [-D Macros]
+GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]
+```
+
+#Description
+**GenCfgOpt.py** is a script that generates configuration options from an
+**EDK II Platform Description (DSC)** file. It has three functions.
+
+ 1. It produces a **.txt** file that is used by the compiler that summarizes
+ the UPD section in the DSC file.
+ 2. It generates header files for the UPD regions.
+ 3. It generates a **Boot Settings File (BSF)** that can be used by the
+ **Binary Configuration Tool (BCT)** to provide a graphical user
+ interface for manipulating settings in the UPD regions.
+
+The **GenCfgOpt.py** script generates important files that are vital parts of
+your build process. The **UPDTXT** and **HEADER** use cases must be done before
+the **'build'** command; the **GENBSF** use case may be done at any time.
+
+The following sections explain the three use cases.
+
+## 1. GenCfgOpt.py UPDTXT
+The **UPDTXT** option creates a text file with all the UPD entries, offsets,
+size in bytes, and values. **GenCfgOpt** reads this information from the
+**[PcdsDynamicVpd.Upd]** section of the project's DSC file. The DSC file allows
+you to specify offsets and sizes for each entry, opening up the possibility of
+introducing gaps between entries. **GenCfgOpt** fills in these gaps with UPD
+entries that have the generic names **UnusedUpdSpaceN** where N begins with 0
+and increments. The command signature for **UPDTXT** is:
+
+```
+GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [TxtOutFile] [-D Macros]
+```
+
+**PlatformDscFile** must be the location of the DSC file for the platform you're
+building. **BuildFvDir** is the location where the binary will be stored. The
+optional **TxtOutFile** is a name and location for the output of **GenCfgOpt**.
+The default name and location is the ```<UPD_TOOL_GUID>.txt``` in the directory
+specified by **BuildFvDir**. The macro ```UPD_TOOL_GUID``` must be defined in
+the DSC file or in the optional Macros arguments. Each optional macro argument
+must follow the form ```?D <MACRO_NAME>=<VALUE>```.
+
+**GenCfgOpt** checks to see if the UPD txt file has already been created and
+will only re-create it if the DSC was modified after it was created.
+
+## 2. GenCfgOpt.py HEADER
+The **HEADER** option creates header files in the build folder. Both header
+files define the ```_UPD_DATA_REGION``` data structures in FspUpd.h, FsptUpd.h,
+FspmUpd.h and FspsUpd.h. In these header files any undefined elements of
+structures will be added as **ReservedUpdSpaceN** beginning with N=0. The
+command signature for **HEADER** is
+
+```GenCfgOpt HEADER PlatformDscFile BuildFvDir [InputHFile] [-D Macros]```
+
+**PlatformDscFile** and **BuildFvDir** are described in the previous section.
+The optional **InputHFile** is a header file that may contain data definitions
+that are used by variables in the UPD regions. This header file must contain
+the special keywords ```!EXPORT EXTERNAL_BOOTLOADER_STRUCT_BEGIN``` and
+```!EXPORT EXTERNAL_BOOTLOADER_STRUCT_END``` in comments. Everything between
+these two keywords will be included in the generated header file.
+The mechanism to specify whether a variable appears as **ReservedUpdSpaceN** in
+the FspUpd.h header file is in special commands that appear in the comments of
+the DSC file. The special commands begin with ```!HDR```, for header. The
+following table summarizes the two command options.
+
+### HEADER
+Use the **HEADER** command to hide specific variables in the public header file.
+In your project DSC file, use ```!HDR HEADER:{OFF}``` at the beginning of the
+section you wish to hide and ```!HDR HEADER:{ON}``` at the end.
+
+### STRUCT
+The **STRUCT** command allows you to specify a specific data type for a
+variable. You can specify a pointer to a data struct, for example. You define
+the data structure in the **InputHFile** between
+```!EXPORT EXTERNAL_BOOTLOADER_STRUCT_BEGIN``` and
+```!EXPORT EXTERNAL_BOOTLOADER_STRUCT_END```.
+
+#####Example:
+```!HDR STRUCT:{MY_DATA_STRUCT*}```
+
+You then define ```MY_DATA_STRUCT``` in **InputHFile**.
+
+### EMBED
+The **EMBED** command allows you to put one or more UPD data into a specify data
+structure. You can utilize it as a group of UPD for example. You must specify a
+start and an end for the specify data structure.
+
+#####Example:
+```
+ !HDR EMBED:{MY_DATA_STRUCT:MyDataStructure:START}
+ gTokenSpaceGuid.Upd1 | 0x0020 | 0x01 | 0x00
+ gTokenSpaceGuid.Upd2 | 0x0021 | 0x01 | 0x00
+ !HDR EMBED:{MY_DATA_STRUCT:MyDataStructure:END}
+ gTokenSpaceGuid.UpdN | 0x0022 | 0x01 | 0x00
+```
+
+#####Result:
+```
+ typedef struct {
+ /** Offset 0x0020
+ **/
+ UINT8 Upd1;
+ /** Offset 0x0021
+ **/
+ UINT8 Upd2;
+ /** Offset 0x0022
+ **/
+ UINT8 UpdN;
+ } MY_DATA_STRUCT;
+
+ typedef struct _UPD_DATA_REGION {
+ ...
+ /** Offset 0x0020
+ **/
+ MY_DATA_STRUCT MyDataStruct;
+ ...
+ } UPD_DATA_REGION;
+```
+
+## 3. GenCfgOpt .py GENBSF
+The **GENBSF** option generates a BSF from the UPD entries in a package's DSC
+file. It does this by parsing special commands found in the comments of the DSC
+file. They roughly match the keywords that define the different sections of the
+BSF.
+
+The command signature for **GENBSF** is
+
+```GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]```
+
+In this case, the **BsfOutFile** parameter is required; it should be the
+relative path to where the BSF should be stored.
+
+Every BSF command in the DSC file begins with **!BSF** or **@Bsf**. The
+following table summarizes the options that come after **!BSF** or **@Bsf**:
+
+# BSF Commands Description
+###PAGES
+**PAGES** maps abbreviations to friendly-text descriptions of the pages in a BSF.
+
+#####Example:
+```!BSF PAGES:{PG1:?Page 1?, PG2:?Page 2?}``` or
+
+```@Bsf PAGES:{PG1:?Page 1?, PG2:?Page 2?}```
+
+###PAGE
+This marks the beginning of a page. Use the abbreviation specified in **PAGES**
+command.
+
+#####Example:
+```!BSF PAGE:{PG1}``` or
+
+```@Bsf PAGE:{PG1}```
+
+All the entries that come after this command are assumed to be on that page,
+until the next **PAGE** command
+
+###FIND
+FIND maps to the BSF **Find** command. It will be placed in the **StructDef**
+region of the BSF and should come at the beginning of the UPD sections of the
+DSC, immediately before the signatures that mark the beginning of these
+sections. The content should be the plain-text equivalent of the signature. The
+signature is usually 8 characters.
+
+#####Example:
+```!BSF FIND:{PROJSIG1}``` or
+
+```@Bsf FIND:{PROJSIG1}```
+
+###BLOCK
+The BLOCK command maps to the **BeginInfoBlock** section of the BSF. There are
+two elements: a version number and a plain-text description.
+
+#####Example:
+```!BSF BLOCK:{NAME:"My platform name", VER:"0.1"}``` or
+
+```@Bsf BLOCK:{NAME:"My platform name", VER:"0.1"}```
+
+###NAME
+**NAME** gives a plain-text for a variable. This is the text label that will
+appear next to the control in **BCT**.
+
+#####Example:
+```!BSF NAME:{Variable 0}``` or
+
+```@Bsf NAME:{Variable 0}```
+
+If the **!BSF NAME** or **@Bsf NAME** command does not appear before an entry
+in the UPD region of the DSC file, then that entry will not appear in the BSF.
+
+###TYPE
+The **TYPE** command is used either by itself or with the **NAME** command. It
+is usually used by itself when defining an **EditNum** field for the BSF. You
+specify the type of data in the second parameter and the range of valid values
+in the third.
+
+#####Example:
+```!BSF TYPE:{EditNum, HEX, (0x00,0xFF)}``` or
+
+```@Bsf TYPE:{EditNum, HEX, (0x00,0xFF)}```
+
+**TYPE** appears on the same line as the **NAME** command when using a combo-box.
+
+#####Example:
+```!BSF NAME:{Variable 1} TYPE:{Combo}``` or
+```@Bsf NAME:{Variable 1} TYPE:{Combo}```
+
+There is a special **None** type that puts the variable in the **StructDef**
+region of the BSF, but doesn't put it in any **Page** section. This makes the
+variable visible to BCT, but not to the end user.
+
+###HELP
+The **HELP** command defines what will appear in the help text for each control
+in BCT.
+
+#####Example:
+```!BSF HELP:{Enable/disable LAN controller.}``` or
+
+```@Bsf HELP:{Enable/disable LAN controller.}```
+
+###OPTION
+The **OPTION** command allows you to custom-define combo boxes and map integer
+or hex values to friendly-text options.
+
+#####Example:
+```!BSF OPTION:{0:IDE, 1:AHCI, 2:RAID}```
+
+```!BSF OPTION:{0x00:0 MB, 0x01:32 MB, 0x02:64 MB}```
+
+or
+
+```@Bsf OPTION:{0:IDE, 1:AHCI, 2:RAID}```
+
+```@Bsf OPTION:{0x00:0 MB, 0x01:32 MB, 0x02:64 MB}```
+
+###FIELD
+The **FIELD** command can be used to define a section of a consolidated PCD
+such that the PCD will be displayed in several fields via BCT interface instead
+of one long entry.
+
+#####Example:
+```!BSF FIELD:{PcdDRAMSpeed:1}``` or
+
+```@Bsf FIELD:{PcdDRAMSpeed:1}```
+
+###ORDER
+The **ORDER** command can be used to adjust the display order for the BSF items.
+By default the order value for a BSF item is assigned to be the UPD item
+```(Offset * 256)```. It can be overridden by declaring **ORDER** command using
+format ORDER: ```{HexMajor.HexMinor}```. In this case the order value will be
+```(HexMajor*256+HexMinor)```. The item order value will be used as the sort key
+during the BSF item display.
+
+#####Example:
+```!BSF ORDER:{0x0040.01}``` or
+
+```@Bsf ORDER:{0x0040.01}```
+
+For **OPTION** and **HELP** commands, it allows to split the contents into
+multiple lines by adding multiple **OPTION** and **HELP** command lines. The
+lines except for the very first line need to start with **+** in the content to
+tell the tool to append this string to the previous one.
+
+For example, the statement
+
+```!BSF OPTION:{0x00:0 MB, 0x01:32 MB, 0x02:64 MB}```
+
+is equivalent to:
+
+```!BSF OPTION:{0x00:0 MB, 0x01:32 MB,}```
+
+```!BSF OPTION:{+ 0x02:64 MB}```
+
+or
+
+```@Bsf OPTION:{0x00:0 MB, 0x01:32 MB, 0x02:64 MB}```
+
+is equivalent to:
+
+```@Bsf OPTION:{0x00:0 MB, 0x01:32 MB,}```
+
+```@Bsf OPTION:{+ 0x02:64 MB}```
+
+The **NAME**, **OPTION**, **TYPE**, and **HELP** commands can all appear on the
+same line following the **!BSF** or **@Bsf** keyword or they may appear on
+separate lines to improve readability.
+
+There are four alternative ways to replace current BSF commands.
+### 1. ```# @Prompt```
+An alternative way replacing **NAME** gives a plain-text for a
+variable. This is the text label that will appear next to the control in BCT.
+
+#####Example:
+```# @Prompt Variable 0```
+
+The above example can replace the two methods as below.
+
+```!BSF NAME:{Variable 0}``` or
+
+```@Bsf NAME:{Variable 0}```
+
+If the ```# @Prompt``` command does not appear before an entry in the UPD region
+of the DSC file, then that entry will not appear in the BSF.
+
+### 2. ```##```
+An alternative way replacing **HELP** command defines what will appear in the
+help text for each control in BCT.
+
+#####Example:
+```## Enable/disable LAN controller.```
+
+The above example can replace the two methods as below.
+
+```!BSF HELP:{Enable/disable LAN controller.}``` or
+
+```@Bsf HELP:{Enable/disable LAN controller.}```
+
+### 3. ```# @ValidList```
+An alternative way replacing **OPTION** command allows you to custom-define
+combo boxes and map integer or hex values to friendly-text options.
+
+#####Example:
+``` # @ValidList 0x80000003 | 0, 1, 2 | IDE, AHCI, RAID
+ Error Code | Options | Descriptions
+```
+
+The above example can replace the two methods as below.
+
+```!BSF OPTION:{0:IDE, 1:AHCI, 2:RAID}``` or
+
+```@Bsf OPTION:{0:IDE, 1:AHCI, 2:RAID}```
+
+### 4. ```# @ValidRange```
+An alternative way replace **EditNum** field for the BSF.
+
+#####Example:
+```# @ValidRange 0x80000001 | 0x0 ? 0xFF
+ Error Code | Range
+```
+
+The above example can replace the two methods as below.
+
+```!BSF TYPE:{EditNum, HEX, (0x00,0xFF)}``` or
+
+```@Bsf TYPE:{EditNum, HEX, (0x00,0xFF)}```
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/PatchFvUserManual.md b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/PatchFvUserManual.md
new file mode 100644
index 00000000..f0b10b18
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/PatchFvUserManual.md
@@ -0,0 +1,123 @@
+#Name
+**_PatchFv.py_** - The python script that patches the firmware volumes (**FV**)
+with in the flash device (**FD**) file post FSP build.
+
+#Synopsis
+
+```
+PatchFv FvBuildDir [FvFileBaseNames:]FdFileBaseNameToPatch ["Offset, Value"]+
+ | ["Offset, Value, @Comment"]+
+ | ["Offset, Value, $Command"]+
+ | ["Offset, Value, $Command, @Comment"]+
+```
+
+#Description
+The **_PatchFv.py_** tool allows the developer to fix up FD images to follow the
+Intel FSP Architecture specification. It also makes the FD image relocatable.
+The tool is written in Python and uses Python 2.7 or later to run.
+Consider using the tool in a build script.
+
+#FvBuildDir (Argument 1)
+This is the first argument that **_PatchFv.py_** requires. It is the build
+directory for all firmware volumes created during the FSP build. The path must
+be either an absolute path or a relevant path, relevant to the top level of the
+FSP tree.
+
+####Example usage:
+```
+ Build\YouPlatformFspPkg\%BD_TARGET%_%VS_VERSION%%VS_X86%\FV
+```
+
+The example used contains Windows batch script %VARIABLES%.
+
+#FvFileBaseNames (Argument 2: Optional Part 1)
+The firmware volume file base names (**_FvFileBaseNames_**) are the independent
+Fv?s that are to be patched within the FD. (0 or more in the form
+**FVFILEBASENAME:**) The colon **:** is used for delimiting the single
+argument and must be appended to the end of each (**_FvFileBaseNames_**).
+
+####Example usage:
+```
+STAGE1:STAGE2:MANIFEST:YOURPLATFORM
+```
+
+In the example **STAGE1** is **STAGE1.Fv** in **YOURPLATFORM.fd**.
+
+# FdFileNameToPatch (Argument 2: Mandatory Part 2)
+
+Firmware device file name to patch (**_FdFileNameToPatch_**) is the base name of
+the FD file that is to be patched. (1 only, in the form **YOURPLATFORM**)
+
+####Example usage:
+```
+STAGE1:STAGE2:MANIFEST:YOURPLATFORM
+```
+
+In the example **YOURPLATFORM** is from **_YOURPLATFORM.fd_**
+
+#"Offset, Value[, Command][, Comment]" (Argument 3)
+The **_Offset_** can be a positive or negative number and represents where the
+**_Value_** to be patched is located within the FD. The **_Value_** is what
+will be written at the given **_Offset_** in the FD. Constants may be used for
+both offsets and values. Also, this argument handles expressions for both
+offsets and values using these operators:
+
+```
+ = - * & | ~ ( ) [ ] { } < >
+```
+
+The entire argument includes the quote marks like in the example argument below:
+
+```
+0xFFFFFFC0, SomeCore:__EntryPoint - [0x000000F0],@SomeCore Entry
+```
+
+###Constants:
+ Hexadecimal (use **0x** as prefix) | Decimal
+
+####Examples:
+
+| **Positive Hex** | **Negative Hex** | **Positive Decimal** | **Negative Decimal** |
+| ---------------: | ---------------: | -------------------: | -------------------: |
+| 0x000000BC | 0xFFFFFFA2 | 188 | -94 |
+
+```
+ModuleName:FunctionName | ModuleName:GlobalVariableName
+ModuleGuid:Offset
+```
+
+###Operators:
+
+```
+
+ + Addition
+ - Subtraction
+ * Multiplication
+ & Logical and
+ | Logical or
+ ~ Complement
+ ( ) Evaluation control
+ [ ] Get a DWord value at the specified offset expression from [expr]
+ { } Convert an offset {expr} into an absolute address (FSP_BASE + expr)
+ < > Convert absolute address <expr> into an image offset (expr & FSP_SIZE)
+
+```
+
+###Special Commands:
+Special commands must use the **$** symbol as a prefix to the command itself.
+There is only one command available at this time.
+
+```
+$COPY ? Copy a binary block from source to destination.
+```
+
+####Example:
+
+```
+0x94, [PlatformInit:__gPcd_BinPatch_FvRecOffset] + 0x94, [0x98], $COPY, @Sync up 2nd FSP Header
+```
+
+###Comments:
+Comments are allowed in the **Offset, Value [, Comment]** argument. Comments
+must use the **@** symbol as a prefix. The comment will output to the build
+window upon successful completion of patching along with the offset and value data.
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/SplitFspBinUserManual.md b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/SplitFspBinUserManual.md
new file mode 100644
index 00000000..ebaa6830
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/SplitFspBinUserManual.md
@@ -0,0 +1,72 @@
+# SplitFspBin.py is a python script to support some operations on Intel FSP 1.x/2.x image.
+
+It supports:
+
+- Split Intel FSP 2.x image into individual FSP-T/M/S/O component
+
+- Rebase Intel FSP 1.x/2.x components to different base addresses
+
+- Generate Intel FSP 1.x/2.x C header file
+
+- Display Intel FSP 1.x/2.x information header for each FSP component
+
+## Split Intel FSP 2.x image
+
+FSP 1.x image is not supported by split command.
+To split individual FSP component in Intel FSP 2.x image, the following
+command can be used:
+
+ **python SplitFspBin.py split [-h] -f FSPBINARY [-o OUTPUTDIR] [-n NAMETEMPLATE]**
+
+For example:
+
+ `python SplitFspBin.py split -f FSP.bin`
+
+ It will create FSP_T.bin, FSP_M.bin and FSP_S.bin in current directory.
+
+## Rebase Intel FSP 1.x/2.x components
+
+To rebase one or multiple FSP components in Intel FSP 1.x/2.x image, the following
+command can be used:
+
+ **python SplitFspBin.py rebase [-h] -f FSPBINARY -c {t,m,s,o} [{t,m,s,o} ...] -b FSPBASE [FSPBASE ...] [-o OUTPUTDIR] [-n OUTPUTFILE]**
+
+For example:
+
+ `python SplitFspBin.py rebase -f FSP.bin -c t -b 0xFFF00000 -n FSP_new.bin`
+
+ It will rebase FSP-T component inside FSP.bin to new base 0xFFF00000 and save the
+ rebased Intel FSP 2.x image into file FSP_new.bin.
+ For FSP 1.x image there is only one component in binary so above command also
+ works for FSP 1.x image.
+
+ `python SplitFspBin.py rebase -f FSP.bin -c t m -b 0xFFF00000 0xFEF80000 -n FSP_new.bin`
+
+ It will rebase FSP-T and FSP-M components inside FSP.bin to new base 0xFFF00000
+ and 0xFEF80000 respectively, and save the rebased Intel FSP 2.x image into file
+ FSP_new.bin file.
+
+## Generate Intel FSP 1.x/2.x C header file
+
+To generate Intel FSP 1.x/2.x C header file, the following command can be used:
+
+ **Python SplitFspBin.py genhdr [-h] -f FSPBINARY [-o OUTPUTDIR] [-n HFILENAME]**
+
+For example:
+
+ `python SplitFspBin.py genhdr -f FSP.bin -n FSP.h`
+
+ It will create the C header file FSP.h containing the image ID, revision, offset
+ and size for each individual FSP component.
+
+## Display Intel FSP 1.x/2.x information header
+
+To display Intel FSP 1.x/2.x information headers, the following command can be used:
+
+ **Python SplitFspBin.py info [-h] -f FSPBINARY**
+
+For example:
+
+ `python SplitFspBin.py info -f FSP.bin`
+
+ It will print out the FSP information header for each FSP component.