IntelFsp2Pkg: FspSecCore support for X64

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3893
1.Added FspSecCore support for X64.
2.Bumped FSP header revision to 7 to indicate FSP 64bit is supported.
3.Corrected few typos.

Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Ashraf Ali S <ashraf.ali.s@intel.com>
Signed-off-by: Ted Kuo <ted.kuo@intel.com>
Reviewed-by: Chasel Chiu <chasel.chiu@intel.com>
Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
This commit is contained in:
Ted Kuo
2022-04-15 01:37:39 -07:00
committed by mergify[bot]
parent d40965b987
commit 00aa71ce20
18 changed files with 1493 additions and 19 deletions

View File

@ -1,7 +1,7 @@
## @file ## @file
# Sec Core for FSP to support MultiPhase (SeparatePhase) SiInitialization. # Sec Core for FSP to support MultiPhase (SeparatePhase) SiInitialization.
# #
# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
# #
@ -17,7 +17,7 @@
# #
# The following information is for reference only and not required by the build tools. # The following information is for reference only and not required by the build tools.
# #
# VALID_ARCHITECTURES = IA32 # VALID_ARCHITECTURES = IA32 X64
# #
[Sources] [Sources]
@ -30,6 +30,12 @@
Ia32/FspApiEntryCommon.nasm Ia32/FspApiEntryCommon.nasm
Ia32/FspHelper.nasm Ia32/FspHelper.nasm
[Sources.X64]
X64/Stack.nasm
X64/Fsp22ApiEntryS.nasm
X64/FspApiEntryCommon.nasm
X64/FspHelper.nasm
[Binaries.Ia32] [Binaries.Ia32]
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC

View File

@ -1,7 +1,7 @@
## @file ## @file
# Sec Core for FSP # Sec Core for FSP
# #
# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
# #
@ -17,7 +17,7 @@
# #
# The following information is for reference only and not required by the build tools. # The following information is for reference only and not required by the build tools.
# #
# VALID_ARCHITECTURES = IA32 # VALID_ARCHITECTURES = IA32 X64
# #
[Sources] [Sources]
@ -34,6 +34,13 @@
Ia32/FspHelper.nasm Ia32/FspHelper.nasm
Ia32/ReadEsp.nasm Ia32/ReadEsp.nasm
[Sources.X64]
X64/Stack.nasm
X64/FspApiEntryM.nasm
X64/FspApiEntryCommon.nasm
X64/FspHelper.nasm
X64/ReadRsp.nasm
[Binaries.Ia32] [Binaries.Ia32]
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC

View File

@ -1,7 +1,7 @@
## @file ## @file
# Sec Core for FSP # Sec Core for FSP
# #
# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
# #
@ -17,7 +17,7 @@
# #
# The following information is for reference only and not required by the build tools. # The following information is for reference only and not required by the build tools.
# #
# VALID_ARCHITECTURES = IA32 # VALID_ARCHITECTURES = IA32 X64
# #
[Sources] [Sources]
@ -30,6 +30,12 @@
Ia32/FspApiEntryCommon.nasm Ia32/FspApiEntryCommon.nasm
Ia32/FspHelper.nasm Ia32/FspHelper.nasm
[Sources.X64]
X64/Stack.nasm
X64/FspApiEntryS.nasm
X64/FspApiEntryCommon.nasm
X64/FspHelper.nasm
[Binaries.Ia32] [Binaries.Ia32]
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC

View File

@ -1,7 +1,7 @@
## @file ## @file
# Sec Core for FSP # Sec Core for FSP
# #
# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
# #
@ -17,17 +17,19 @@
# #
# The following information is for reference only and not required by the build tools. # The following information is for reference only and not required by the build tools.
# #
# VALID_ARCHITECTURES = IA32 # VALID_ARCHITECTURES = IA32 X64
# #
[Sources]
[Sources.IA32] [Sources.IA32]
Ia32/Stack.nasm Ia32/Stack.nasm
Ia32/FspApiEntryT.nasm Ia32/FspApiEntryT.nasm
Ia32/FspHelper.nasm Ia32/FspHelper.nasm
[Sources.X64]
X64/Stack.nasm
X64/FspApiEntryT.nasm
X64/FspHelper.nasm
[Binaries.Ia32] [Binaries.Ia32]
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC

View File

@ -1,12 +1,14 @@
;; @file ;; @file
; Provide FSP API entry points. ; Provide FSP API entry points.
; ;
; Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR> ; Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent ; SPDX-License-Identifier: BSD-2-Clause-Patent
;; ;;
SECTION .text SECTION .text
STACK_SAVED_EAX_OFFSET EQU 4 * 7 ; size of a general purpose register * eax index
; ;
; Following functions will be provided in C ; Following functions will be provided in C
; ;
@ -52,7 +54,7 @@ FspApiCommon1:
add esp, 8 add esp, 8
cmp eax, 0 cmp eax, 0
jz FspApiCommon2 jz FspApiCommon2
mov dword [esp + (4 * 7)], eax mov dword [esp + STACK_SAVED_EAX_OFFSET], eax
popad popad
exit: exit:
ret ret

View File

@ -0,0 +1,103 @@
;; @file
; Provide FSP API entry points.
;
; Copyright (c) 2022, 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)
STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index
;----------------------------------------------------------------------------
; 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.
;
;----------------------------------------------------------------------------
%include "PushPopRegsNasm.inc"
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
PUSHA_64
mov rdx, rcx ; move ApiParam to rdx
mov rcx, rax ; move ApiIdx to rcx
call ASM_PFX(FspMultiPhaseSiInitApiHandler)
mov qword [rsp + STACK_SAVED_RAX_OFFSET], rax
POPA_64
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 $

View File

@ -0,0 +1,76 @@
;; @file
; Provide FSP API entry points.
;
; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;;
SECTION .text
%include "PushPopRegsNasm.inc"
STACK_SAVED_RAX_OFFSET EQU 8 * 7 ; size of a general purpose register * rax index
;
; 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):
;
; RAX holds the API index
;
;
; Stack must be ready
;
push rax
add rsp, 8
cmp rax, [rsp - 8]
jz FspApiCommon1
mov rax, 08000000000000003h
jmp exit
FspApiCommon1:
;
; Verify the calling condition
;
PUSHA_64
mov rdx, rcx ; move ApiParam to rdx
mov rcx, rax ; move ApiIdx to rcx
call ASM_PFX(FspApiCallingCheck)
cmp rax, 0
jz FspApiCommon2
mov [rsp + STACK_SAVED_RAX_OFFSET], rax
POPA_64
exit:
ret
FspApiCommon2:
POPA_64
cmp rax, 3 ; FspMemoryInit API
jz FspApiCommon3
cmp rax, 6 ; FspMultiPhaseSiInitApiIndex API
jz FspApiCommon3
call ASM_PFX(AsmGetFspInfoHeader)
jmp ASM_PFX(Loader2PeiSwitchStack)
FspApiCommon3:
jmp ASM_PFX(FspApiCommonContinue)

View File

@ -0,0 +1,271 @@
;; @file
; Provide FSP API entry points.
;
; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;;
SECTION .text
%include "PushPopRegsNasm.inc"
;
; Following are fixed PCDs
;
extern ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))
struc FSPM_UPD_COMMON_FSP24
; FSP_UPD_HEADER {
.FspUpdHeader: resd 8
; }
; FSPM_ARCH2_UPD {
.Revision: resb 1
.Reserved: resb 3
.Length resd 1
.StackBase: resq 1
.StackSize: resq 1
.BootLoaderTolumSize: resd 1
.BootMode: resd 1
.FspEventHandler resq 1
.Reserved1: resb 24
; }
.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)
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):
;
; RAX holds the API index
; Push RDX and RCX to form CONTEXT_STACK_64
;
push rdx ; Push a QWORD data for stack alignment
push rdx ; Push API Parameter2 on stack
push rcx ; Push API Parameter1 on stack
;
; FspMemoryInit API setup the initial stack frame
;
;
; Place holder to store the FspInfoHeader pointer
;
push rax
;
; Update the FspInfoHeader pointer
;
push rax
call ASM_PFX(AsmGetFspInfoHeader)
mov [rsp + 8], rax
pop rax
;
; Create a Task Frame in the stack for the Boot Loader
;
pushfq
cli
PUSHA_64
; Reserve 16 bytes for IDT save/restore
sub rsp, 16
sidt [rsp]
; Get Stackbase and StackSize from FSPM_UPD Param
mov rdx, rcx ; Put FSPM_UPD Param to rdx
cmp rdx, 0
jnz FspStackSetup
; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null
xchg rbx, rax
call ASM_PFX(AsmGetFspInfoHeader)
mov edx, [rax + FSP_HEADER_IMGBASE_OFFSET]
add edx, [rax + FSP_HEADER_CFGREG_OFFSET]
xchg rbx, rax
FspStackSetup:
mov cl, [rdx + FSPM_UPD_COMMON_FSP24.Revision]
cmp cl, 3
jae FspmUpdCommonFsp24
mov rax, 08000000000000002h ; RETURN_INVALID_PARAMETER
sub rsp, 0b8h
ret
FspmUpdCommonFsp24:
;
; StackBase = temp memory base, StackSize = temp memory size
;
mov rdi, [rdx + FSPM_UPD_COMMON_FSP24.StackBase]
mov ecx, [rdx + FSPM_UPD_COMMON_FSP24.StackSize]
;
; Keep using bootloader stack if heap size % is 0
;
mov rbx, ASM_PFX(PcdGet8 (PcdFspHeapSizePercentage))
mov bl, BYTE [rbx]
cmp bl, 0
jz SkipStackSwitch
;
; Set up a dedicated temp ram stack for FSP if FSP heap size % doesn't equal 0
;
add rdi, rcx
;
; Switch to new FSP stack
;
xchg rdi, rsp ; Exchange rdi and rsp, rdi will be assigned to the current rsp pointer and rsp will be Stack base + Stack size
SkipStackSwitch:
;
; If heap size % is 0:
; EDI is FSPM_UPD_COMMON_FSP24.StackBase and will hold ESP later (boot loader stack pointer)
; ECX is FSPM_UPD_COMMON_FSP24.StackSize
; ESP is boot loader stack pointer (no stack switch)
; BL is 0 to indicate no stack switch (EBX will hold FSPM_UPD_COMMON_FSP24.StackBase later)
;
; If heap size % is not 0
; EDI is boot loader stack pointer
; ECX is FSPM_UPD_COMMON_FSP24.StackSize
; ESP is new stack (FSPM_UPD_COMMON_FSP24.StackBase + FSPM_UPD_COMMON_FSP24.StackSize)
; BL is NOT 0 to indicate stack has switched
;
cmp bl, 0
jnz StackHasBeenSwitched
mov rbx, rdi ; Put FSPM_UPD_COMMON_FSP24.StackBase to rbx as temp memory base
mov rdi, rsp ; Put boot loader stack pointer to rdi
jmp StackSetupDone
StackHasBeenSwitched:
mov rbx, rsp ; Put Stack base + Stack size in ebx
sub rbx, rcx ; Stack base + Stack size - Stack size as temp memory base
StackSetupDone:
;
; Per X64 calling convention, make sure RSP is 16-byte aligned.
;
mov rdx, rsp
and rdx, 0fh
sub rsp, rdx
;
; Pass the API Idx to SecStartup
;
push rax
;
; Pass the BootLoader stack to SecStartup
;
push rdi
;
; 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)
mov r8, rax
;
; Pass entry point of the PEI core
;
call ASM_PFX(AsmGetPeiCoreOffset)
lea r9, [r8 + rax]
;
; Pass stack base and size into the PEI Core
;
mov rcx, rcx
mov rdx, rbx
;
; Pass Control into the PEI Core
; RCX = SizeOfRam, RDX = TempRamBase, R8 = BFV, R9 = PeiCoreEntry, Last 1 Stack = BL stack, Last 2 Stack = API index
; According to X64 calling convention, caller has to allocate 32 bytes as a shadow store on call stack right before
; calling the function.
;
sub rsp, 20h
call ASM_PFX(SecStartup)
add rsp, 20h
exit:
ret
global ASM_PFX(FspPeiCoreEntryOff)
ASM_PFX(FspPeiCoreEntryOff):
;
; This value will be patched by the build script
;
DD 0x12345678
global ASM_PFX(AsmGetPeiCoreOffset)
ASM_PFX(AsmGetPeiCoreOffset):
push rbx
mov rbx, ASM_PFX(FspPeiCoreEntryOff)
mov eax, dword[ebx]
pop rbx
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 $

View File

@ -0,0 +1,67 @@
;; @file
; Provide FSP API entry points.
;
; Copyright (c) 2022, 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 $

View File

@ -0,0 +1,495 @@
;; @file
; Provide FSP API entry points.
;
; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;;
SECTION .text
%include "SaveRestoreSseAvxNasm.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 LoadMicrocodeParamsFsp24
; FSP_UPD_HEADER {
.FspUpdHeaderSignature: resd 2
.FspUpdHeaderRevision: resb 1
.FspUpdHeaderReserved: resb 23
; }
; FSPT_ARCH2_UPD {
.FsptArchRevision: resb 1
.FsptArchReserved: resb 3
.FsptArchLength: resd 1
.FspDebugHandler resq 1
.FsptArchUpd: resd 4
; }
; FSPT_CORE_UPD {
.MicrocodeCodeAddr: resq 1
.MicrocodeCodeSize: resq 1
.CodeRegionBase: resq 1
.CodeRegionSize: resq 1
; }
.size:
endstruc
;
; @todo: The strong/weak implementation does not work.
; This needs to be reviewed later.
;
;------------------------------------------------------------------------------
;
;;global ASM_PFX(SecPlatformInitDefault)
;ASM_PFX(SecPlatformInitDefault):
; ; Inputs:
; ; ymm7 -> Return address
; ; Outputs:
; ; rax -> 0 - Successful, Non-zero - Failed.
; ; Register Usage:
; ; rax is cleared and rbp is used for return address.
; ; All others reserved.
;
; ; Save return address to RBP
; LOAD_RBP
;
; xor rax, rax
;Exit1:
; jmp rbp
;------------------------------------------------------------------------------
global ASM_PFX(LoadMicrocodeDefault)
ASM_PFX(LoadMicrocodeDefault):
; Inputs:
; rsp -> LoadMicrocodeParams pointer
; Register Usage:
; rsp 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 RBP
;
LOAD_RBP
cmp rsp, 0
jz ParamError
mov eax, dword [rsp + 8] ; 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 [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
jb ParamError
cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
jne ParamError
; UPD structure is compliant with FSP spec 2.4
mov eax, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
cmp eax, 0
jz Exit2
cmp eax, 0800h
jl ParamError
mov esi, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
cmp esi, 0
jnz CheckMainHeader
ParamError:
mov rax, 08000000000000002h
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 rax, rax
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 rax, rax
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 [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
jb ParamError
cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
jne ParamError
; UPD structure is compliant with FSP spec 2.4
; Is automatic size detection ?
mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
cmp rax, 0ffffffffffffffffh
jz LoadMicrocodeDefault4
; Address >= microcode region address + microcode region size?
add rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
cmp rsi, rax
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, 0800000000000000Eh
Exit2:
jmp rbp
global ASM_PFX(EstablishStackFsp)
ASM_PFX(EstablishStackFsp):
;
; Save parameter pointer in rdx
;
mov rdx, qword [rsp + 8]
;
; Enable FSP STACK
;
mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
mov esp, DWORD[rax]
mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
add esp, DWORD[rax]
sub esp, 4
mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region
sub esp, 4
mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'
; check UPD structure revision (rdx + 8)
cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
jb ParamError1
cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
je Fsp24UpdHeader
ParamError1:
mov rax, 08000000000000002h
jmp EstablishStackFspExit
Fsp24UpdHeader:
; UPD structure is compliant with FSP spec 2.4
xor rax, rax
mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h
sub rsp, 8
mov qword[rsp], rax
mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h
sub rsp, 8
mov qword[rsp], rax
mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h
sub rsp, 8
mov qword[rsp], rax
mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h
sub rsp, 8
mov qword[rsp], rax
ContinueAfterUpdPush:
;
; Save API entry/exit timestamp into stack
;
sub esp, 4
mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region
sub esp, 4
mov dword[esp], 30524550h ; Signature of the data region 'PER0'
rdtsc
sub esp, 4
mov dword[esp], edx
sub esp, 4
mov dword[esp], eax
LOAD_TS rax
push rax
;
; Terminator for the data on stack
;
push 0
;
; Set ECX/EDX to the BootLoader temporary memory range
;
mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
mov edx, [ecx]
mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
add edx, [ecx]
mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
sub edx, [ecx]
mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
mov ecx, [ecx]
cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
jb EstablishStackFspSuccess
mov rax, 08000000000000003h ; EFI_UNSUPPORTED
jmp EstablishStackFspExit
EstablishStackFspSuccess:
xor rax, rax
EstablishStackFspExit:
RET_YMM
;----------------------------------------------------------------------------
; 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 both SSE and AVX are enabled
;
ENABLE_SSE
ENABLE_AVX
;
; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6
;
SAVE_REGS
;
; Save BFV address in YMM9
;
SAVE_BFV rbp
;
; Save timestamp into YMM6
;
rdtsc
shl rdx, 32
or rax, rdx
SAVE_TS rax
;
; Check Parameter
;
mov rax, qword [rsp + 8]
cmp rax, 0
mov rax, 08000000000000002h
jz TempRamInitExit
;
; Sec Platform Init
;
CALL_YMM ASM_PFX(SecPlatformInit)
cmp eax, 0
jnz TempRamInitExit
; Load microcode
LOAD_RSP
CALL_YMM ASM_PFX(LoadMicrocodeDefault)
SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).
; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.
; Call Sec CAR Init
LOAD_RSP
CALL_YMM ASM_PFX(SecCarInit)
cmp rax, 0
jnz TempRamInitExit
LOAD_RSP
CALL_YMM ASM_PFX(EstablishStackFsp)
cmp rax, 0
jnz TempRamInitExit
LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).
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 RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6
;
LOAD_REGS
LOAD_BFV rbp
ret
;----------------------------------------------------------------------------
; Module Entrypoint API
;----------------------------------------------------------------------------
global ASM_PFX(_ModuleEntryPoint)
ASM_PFX(_ModuleEntryPoint):
jmp $

View File

@ -0,0 +1,34 @@
;; @file
; Provide FSP helper function.
;
; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;;
DEFAULT REL
SECTION .text
global ASM_PFX(AsmGetFspBaseAddress)
ASM_PFX(AsmGetFspBaseAddress):
call ASM_PFX(AsmGetFspInfoHeader)
add rax, 0x1C
mov eax, [rax]
ret
global ASM_PFX(AsmGetFspInfoHeader)
ASM_PFX(AsmGetFspInfoHeader):
lea rax, [ASM_PFX(AsmGetFspInfoHeader)]
DB 0x48, 0x2d ; sub rax, 0x????????
global ASM_PFX(FspInfoHeaderRelativeOff)
ASM_PFX(FspInfoHeaderRelativeOff):
DD 0x12345678 ; This value must be patched by the build script
and rax, 0xffffffff
ret
global ASM_PFX(AsmGetFspInfoHeaderNoStack)
ASM_PFX(AsmGetFspInfoHeaderNoStack):
lea rax, [ASM_PFX(AsmGetFspInfoHeader)]
lea rcx, [ASM_PFX(FspInfoHeaderRelativeOff)]
mov ecx, [rcx]
sub rax, rcx
and rax, 0xffffffff
jmp rdi

View File

@ -0,0 +1,11 @@
;; @file
;
;@copyright
; Copyright (c) 2022, 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

View File

@ -0,0 +1,22 @@
;; @file
; Provide read RSP function
;
; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;;
;------------------------------------------------------------------------------
SECTION .text
;------------------------------------------------------------------------------
; UINTN
; EFIAPI
; AsmReadStackPointer (
; VOID
; );
;------------------------------------------------------------------------------
global ASM_PFX(AsmReadStackPointer)
ASM_PFX(AsmReadStackPointer):
mov rax, rsp
ret

View File

@ -0,0 +1,73 @@
;------------------------------------------------------------------------------
;
; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Abstract:
;
; Switch the stack from temporary memory to permanent memory.
;
;------------------------------------------------------------------------------
SECTION .text
;------------------------------------------------------------------------------
; VOID
; EFIAPI
; SecSwitchStack (
; UINT64 TemporaryMemoryBase,
; UINT64 PermanentMemoryBase
; );
;------------------------------------------------------------------------------
global ASM_PFX(SecSwitchStack)
ASM_PFX(SecSwitchStack):
;
; Save four register: rax, rbx, rcx, rdx
;
push rax
push rbx
push rcx
push rdx
;
; !!CAUTION!! this function address's is pushed into stack after
; migration of whole temporary memory, so need save it to permanent
; memory at first!
;
mov rbx, rcx ; Save the first parameter
mov rcx, rdx ; Save the second parameter
;
; Save this function's return address into permanent memory at first.
; Then, Fixup the esp point to permanent memory
;
mov rax, rsp
sub rax, rbx
add rax, rcx
mov rdx, qword [rsp] ; copy pushed register's value to permanent memory
mov qword [rax], rdx
mov rdx, qword [rsp + 8]
mov qword [rax + 8], rdx
mov rdx, qword [rsp + 16]
mov qword [rax + 16], rdx
mov rdx, qword [rsp + 24]
mov qword [rax + 24], rdx
mov rdx, qword [rsp + 32] ; Update this function's return address into permanent memory
mov qword [rax + 32], rdx
mov rsp, rax ; From now, rsp is pointed to permanent memory
;
; Fixup the rbp point to permanent memory
;
mov rax, rbp
sub rax, rbx
add rax, rcx
mov rbp, rax ; From now, rbp is pointed to permanent memory
pop rdx
pop rcx
pop rbx
pop rax
ret

View File

@ -2,11 +2,13 @@
Intel FSP Header File definition from Intel Firmware Support Package External Intel FSP Header File definition from Intel Firmware Support Package External
Architecture Specification v2.0 and above. Architecture Specification v2.0 and above.
Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
#include <Base.h>
#ifndef __FSP_HEADER_FILE_H__ #ifndef __FSP_HEADER_FILE_H__
#define __FSP_HEADER_FILE_H__ #define __FSP_HEADER_FILE_H__
@ -24,6 +26,12 @@
#define FSP_INFO_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'H') #define FSP_INFO_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'H')
#define IMAGE_ATTRIBUTE_GRAPHICS_SUPPORT BIT0
#define IMAGE_ATTRIBUTE_DISPATCH_MODE_SUPPORT BIT1
#define IMAGE_ATTRIBUTE_64BIT_MODE_SUPPORT BIT2
#define FSP_IA32 0
#define FSP_X64 1
#pragma pack(1) #pragma pack(1)
/// ///
@ -49,7 +57,7 @@ typedef struct {
UINT8 SpecVersion; UINT8 SpecVersion;
/// ///
/// Byte 0x0B: Revision of the FSP Information Header. /// Byte 0x0B: Revision of the FSP Information Header.
/// The Current value for this field is 0x6. /// The Current value for this field is 0x7.
/// ///
UINT8 HeaderRevision; UINT8 HeaderRevision;
/// ///
@ -82,6 +90,10 @@ typedef struct {
UINT32 ImageBase; UINT32 ImageBase;
/// ///
/// Byte 0x20: Attribute for the FSP binary. /// Byte 0x20: Attribute for the FSP binary.
/// Bit 0: Graphics Support - Set to 1 when FSP supports enabling Graphics Display.
/// Bit 1: Dispatch Mode Support - Set to 1 when FSP supports the optional Dispatch Mode API defined in Section 7.2 and 9. This bit is only valid if FSP HeaderRevision is >= 4.
/// Bit 2: 64-bit mode support - Set to 1 to indicate FSP supports 64-bit long mode interfaces. Set to 0 to indicate FSP supports 32-bit mode interfaces. This bit is only valid if FSP HeaderRevision is >= 7.
/// Bits 15:3 - Reserved
/// ///
UINT16 ImageAttribute; UINT16 ImageAttribute;
/// ///

View File

@ -0,0 +1,284 @@
;------------------------------------------------------------------------------
;
; Copyright (c) 2022, 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 and AVX instruction set
;
;
; Define SSE macros using SSE 4.1 instructions
; args 1:XMM, 2:IDX, 3:REG
;
%macro SXMMN 3
pinsrq %1, %3, (%2 & 3)
%endmacro
;
; args 1:XMM, 2:REG, 3:IDX
;
%macro LXMMN 3
pextrq %2, %1, (%3 & 3)
%endmacro
;
; Define AVX macros using AVX instructions
; Save XMM to YMM
; args 1:YMM, 2:IDX (0 - lower 128bits, 1 - upper 128bits), 3:XMM
;
%macro SYMMN 3
vinsertf128 %1, %1, %3, %2
%endmacro
;
; Restore XMM from YMM
; args 1:YMM, 2:XMM, 3:IDX (0 - lower 128bits, 1 - upper 128bits)
;
%macro LYMMN 3
vextractf128 %2, %1, %3
%endmacro
;
; Upper half of YMM7 to save RBP and RBX. Upper half of YMM8 to save RSI and RDI.
; Modified: XMM5, YMM6, YMM7 and YMM8
;
%macro SAVE_REGS 0
SXMMN xmm5, 0, rbp
SXMMN xmm5, 1, rbx
SYMMN ymm7, 1, xmm5
SXMMN xmm5, 0, rsi
SXMMN xmm5, 1, rdi
SYMMN ymm8, 1, xmm5
SAVE_RSP
%endmacro
;
; Upper half of YMM7 to restore RBP and RBX. Upper half of YMM8 to restore RSI and RDI.
; Modified: XMM5, RBP, RBX, RSI, RDI and RSP
;
%macro LOAD_REGS 0
LYMMN ymm7, xmm5, 1
LXMMN xmm5, rbp, 0
LXMMN xmm5, rbx, 1
LYMMN ymm8, xmm5, 1
LXMMN xmm5, rsi, 0
LXMMN xmm5, rdi, 1
LOAD_RSP
%endmacro
;
; Restore RBP from YMM7[128:191]
; Modified: XMM5 and RBP
;
%macro LOAD_RBP 0
LYMMN ymm7, xmm5, 1
movq rbp, xmm5
%endmacro
;
; Restore RBX from YMM7[192:255]
; Modified: XMM5 and RBX
;
%macro LOAD_RBX 0
LYMMN ymm7, xmm5, 1
LXMMN xmm5, rbx, 1
%endmacro
;
; Upper half of YMM6 to save/restore Time Stamp, RSP
;
;
; Save Time Stamp to YMM6[192:255]
; arg 1:general purpose register which holds time stamp
; Modified: XMM5 and YMM6
;
%macro SAVE_TS 1
LYMMN ymm6, xmm5, 1
SXMMN xmm5, 1, %1
SYMMN ymm6, 1, xmm5
%endmacro
;
; Restore Time Stamp from YMM6[192:255]
; arg 1:general purpose register where to save time stamp
; Modified: XMM5 and %1
;
%macro LOAD_TS 1
LYMMN ymm6, xmm5, 1
LXMMN xmm5, %1, 1
%endmacro
;
; Save RSP to YMM6[128:191]
; Modified: XMM5 and YMM6
;
%macro SAVE_RSP 0
LYMMN ymm6, xmm5, 1
SXMMN xmm5, 0, rsp
SYMMN ymm6, 1, xmm5
%endmacro
;
; Restore RSP from YMM6[128:191]
; Modified: XMM5 and RSP
;
%macro LOAD_RSP 0
LYMMN ymm6, xmm5, 1
movq rsp, xmm5
%endmacro
;
; Upper half of YMM9 to save/restore UCODE status, BFV address
;
;
; Save uCode status to YMM9[192:255]
; arg 1:general purpose register which holds uCode status
; Modified: XMM5 and YMM9
;
%macro SAVE_UCODE_STATUS 1
LYMMN ymm9, xmm5, 1
SXMMN xmm5, 0, %1
SYMMN ymm9, 1, xmm5
%endmacro
;
; Restore uCode status from YMM9[192:255]
; arg 1:general purpose register where to save uCode status
; Modified: XMM5 and %1
;
%macro LOAD_UCODE_STATUS 1
LYMMN ymm9, xmm5, 1
movq %1, xmm5
%endmacro
;
; Save BFV address to YMM9[128:191]
; arg 1:general purpose register which holds BFV address
; Modified: XMM5 and YMM9
;
%macro SAVE_BFV 1
LYMMN ymm9, xmm5, 1
SXMMN xmm5, 1, %1
SYMMN ymm9, 1, xmm5
%endmacro
;
; Restore BFV address from YMM9[128:191]
; arg 1:general purpose register where to save BFV address
; Modified: XMM5 and %1
;
%macro LOAD_BFV 1
LYMMN ymm9, xmm5, 1
LXMMN xmm5, %1, 1
%endmacro
;
; YMM7[128:191] for calling stack
; arg 1:Entry
; Modified: RSI, XMM5, YMM7
;
%macro CALL_YMM 1
mov rsi, %%ReturnAddress
LYMMN ymm7, xmm5, 1
SXMMN xmm5, 0, rsi
SYMMN ymm7, 1, xmm5
mov rsi, %1
jmp rsi
%%ReturnAddress:
%endmacro
;
; Restore RIP from YMM7[128:191]
; Modified: RSI, XMM5
;
%macro RET_YMM 0
LYMMN ymm7, xmm5, 1
movq rsi, xmm5
jmp rsi
%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 DQ 01F80h
SseError:
;
; Processor has to support SSE
;
jmp SseError
NextAddress:
finit
mov rax, FpuControlWord
fldcw [rax]
;
; Use CpuId instruction (CPUID.01H:EDX.SSE[bit 25] = 1) to test
; whether the processor supports SSE instruction.
;
mov rax, 1
cpuid
bt rdx, 25
jnc SseError
;
; SSE 4.1 support
;
bt ecx, 19
jnc SseError
;
; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
;
mov rax, cr4
or rax, 00000600h
mov cr4, rax
;
; The processor should support SSE instruction and we can use
; ldmxcsr instruction
;
mov rax, MmxControlWord
ldmxcsr [rax]
%endmacro
%macro ENABLE_AVX 0
mov eax, 1
cpuid
and ecx, 10000000h
cmp ecx, 10000000h ; check AVX feature flag
je EnableAvx
AvxError:
;
; Processor has to support AVX
;
jmp AvxError
EnableAvx:
;
; Set OSXSAVE bit (bit #18) to enable xgetbv/xsetbv instruction
;
mov rax, cr4
or rax, 00040000h
mov cr4, rax
mov rcx, 0 ; index 0
xgetbv ; result in edx:eax
or eax, 00000006h ; Set XCR0 bit #1 and bit #2 to enable SSE state and AVX state
xsetbv
%endmacro

View File

@ -1,6 +1,6 @@
/** @file /** @file
Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR> Copyright (c) 2014 - 2022, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
@ -38,7 +38,8 @@ typedef struct {
} CONTEXT_STACK; } CONTEXT_STACK;
// //
// API return address +0xB0 // API return address +0xB8
// Reserved +0xB0
// push API Parameter2 +0xA8 // push API Parameter2 +0xA8
// push API Parameter1 +0xA0 // push API Parameter1 +0xA0
// push FspInfoHeader +0x98 // push FspInfoHeader +0x98
@ -54,6 +55,7 @@ typedef struct {
UINT32 Flags[2]; UINT32 Flags[2];
UINT64 FspInfoHeader; UINT64 FspInfoHeader;
UINT64 ApiParam[2]; UINT64 ApiParam[2];
UINT64 Reserved; // The reserved QWORD is needed for stack alignment in X64.
UINT64 ApiRet; // 64bit stack format is different from the 32bit one due to x64 calling convention UINT64 ApiRet; // 64bit stack format is different from the 32bit one due to x64 calling convention
} CONTEXT_STACK_64; } CONTEXT_STACK_64;

View File

@ -47,7 +47,8 @@ ASM_PFX(Loader2PeiSwitchStack):
;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------
global ASM_PFX(FspSwitchStack) global ASM_PFX(FspSwitchStack)
ASM_PFX(FspSwitchStack): ASM_PFX(FspSwitchStack):
; Save current contexts ; Save current contexts. The format must align with CONTEXT_STACK_64.
push rdx ; Reserved QWORD for stack alignment
push rdx ; ApiParam2 push rdx ; ApiParam2
push rcx ; ApiParam1 push rcx ; ApiParam1
push rax ; FspInfoHeader push rax ; FspInfoHeader
@ -67,6 +68,6 @@ ASM_PFX(FspSwitchStack):
add rsp, 16 add rsp, 16
POPA_64 POPA_64
popfq popfq
add rsp, 24 ; FspInfoHeader + ApiParam[2] add rsp, 32 ; FspInfoHeader + ApiParam[2] + Reserved QWORD
ret ret