diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore | |
parent | Initial commit. (diff) | |
download | virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
24 files changed, 2669 insertions, 0 deletions
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 Binary files differnew file mode 100644 index 00000000..2dc9f178 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw 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() + |