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:
495
IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm
Normal file
495
IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm
Normal 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 $
|
||||
|
Reference in New Issue
Block a user