Add IntelFspPkg to support create FSP bin based on EDKII.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed off by: Ravi Rangarajan <ravi.p.rangarajan@intel.com> Reviewed by: Maurice Ma <maurice.ma@intel.com> Reviewed by: Jiewen Yao <jiewen.yao@intel.com> Reviewed by: Giri Mudusuru <giri.p.mudusuru@intel.com> Reviewed by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15705 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
76
IntelFspPkg/FspSecCore/FspSecCore.inf
Normal file
76
IntelFspPkg/FspSecCore/FspSecCore.inf
Normal file
@@ -0,0 +1,76 @@
|
||||
## @file
|
||||
#
|
||||
# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = FspSecCore
|
||||
FILE_GUID = 1BA0062E-C779-4582-8566-336AE8F78F09
|
||||
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
|
||||
|
||||
[Sources.IA32]
|
||||
Ia32/ResetVec.asm16 | MSFT
|
||||
Ia32/Stack.asm | MSFT
|
||||
Ia32/InitializeFpu.asm | MSFT
|
||||
Ia32/FspApiEntry.asm | MSFT
|
||||
|
||||
Ia32/Stacks.s | GCC
|
||||
Ia32/InitializeFpu.s | GCC
|
||||
Ia32/FspApiEntry.s | GCC
|
||||
|
||||
[Binaries.Ia32]
|
||||
RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC
|
||||
|
||||
[Binaries.X64]
|
||||
RAW|Vtf0/Bin/ResetVec.x64.raw |GCC
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
IntelFspPkg/IntelFspPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
BaseLib
|
||||
PciCf8Lib
|
||||
SerialPortLib
|
||||
FspSwitchStackLib
|
||||
FspCommonLib
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
|
||||
gIntelFspPkgTokenSpaceGuid.PcdGlobalDataPointerAddress
|
||||
gIntelFspPkgTokenSpaceGuid.PcdTemporaryRamBase
|
||||
gIntelFspPkgTokenSpaceGuid.PcdTemporaryRamSize
|
||||
gIntelFspPkgTokenSpaceGuid.PcdFspTemporaryRamSize
|
||||
|
||||
[FixedPcd]
|
||||
gIntelFspPkgTokenSpaceGuid.PcdFspMaxPatchEntry
|
||||
gIntelFspPkgTokenSpaceGuid.PcdFspMaxPerfEntry
|
||||
|
||||
[Ppis]
|
||||
gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
|
||||
|
552
IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
Normal file
552
IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
Normal file
@@ -0,0 +1,552 @@
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php.
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Provide FSP API entry points.
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
.586p
|
||||
.model flat,C
|
||||
.code
|
||||
.xmm
|
||||
|
||||
INCLUDE SaveRestoreSse.inc
|
||||
INCLUDE UcodeLoad.inc
|
||||
|
||||
;
|
||||
; Following are fixed PCDs
|
||||
;
|
||||
EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
|
||||
EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
|
||||
EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
|
||||
|
||||
;
|
||||
; Following functions will be provided in C
|
||||
;
|
||||
EXTERN FspImageSizeOffset:DWORD
|
||||
EXTERN SecStartup:PROC
|
||||
EXTERN FspApiCallingCheck:PROC
|
||||
|
||||
;
|
||||
; Following functions will be provided in PlatformSecLib
|
||||
;
|
||||
EXTERN GetFspBaseAddress:PROC
|
||||
EXTERN GetBootFirmwareVolumeOffset:PROC
|
||||
EXTERN PlatformTempRamInit:PROC
|
||||
EXTERN Pei2LoaderSwitchStack:PROC
|
||||
EXTERN FspSelfCheck(FspSelfCheckDflt):PROC
|
||||
EXTERN PlatformBasicInit(PlatformBasicInitDflt):PROC
|
||||
EXTERN LoadUcode(LoadUcodeDflt):PROC
|
||||
|
||||
;
|
||||
; 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)
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
FspSelfCheckDflt PROC NEAR PUBLIC
|
||||
; Inputs:
|
||||
; eax -> 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
|
||||
mov ebp, eax
|
||||
|
||||
xor eax, eax
|
||||
exit:
|
||||
jmp ebp
|
||||
FspSelfCheckDflt ENDP
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
PlatformBasicInitDflt PROC NEAR PUBLIC
|
||||
; Inputs:
|
||||
; eax -> 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
|
||||
mov ebp, eax
|
||||
|
||||
xor eax, eax
|
||||
exit:
|
||||
jmp ebp
|
||||
PlatformBasicInitDflt ENDP
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
LoadUcodeDflt PROC NEAR PUBLIC
|
||||
; Inputs:
|
||||
; esp -> LOAD_UCODE_PARAMS 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
|
||||
mov ebp, eax
|
||||
|
||||
cmp esp, 0
|
||||
jz paramerror
|
||||
mov eax, dword ptr [esp] ; Parameter pointer
|
||||
cmp eax, 0
|
||||
jz paramerror
|
||||
mov esp, eax
|
||||
mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
|
||||
cmp esi, 0
|
||||
jnz check_main_header
|
||||
|
||||
paramerror:
|
||||
mov eax, 080000002h
|
||||
jmp exit
|
||||
|
||||
mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
|
||||
|
||||
check_main_header:
|
||||
; 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
|
||||
and ecx, 7h
|
||||
mov edx, 1
|
||||
shl edx, cl
|
||||
|
||||
; Current register usage
|
||||
; esp -> stack with paramters
|
||||
; 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 ptr 1
|
||||
cmp [esi].ucode_hdr.version, eax
|
||||
jne advance_fixed_size
|
||||
cmp [esi].ucode_hdr.loader, eax
|
||||
jne advance_fixed_size
|
||||
|
||||
; Check if signature and plaform ID match
|
||||
cmp ebx, [esi].ucode_hdr.processor
|
||||
jne @f
|
||||
test edx, [esi].ucode_hdr.flags
|
||||
jnz load_check ; Jif signature and platform ID match
|
||||
|
||||
@@:
|
||||
; Check if extended header exists
|
||||
; First check if total_size and data_size are valid
|
||||
xor eax, eax
|
||||
cmp [esi].ucode_hdr.total_size, eax
|
||||
je next_microcode
|
||||
cmp [esi].ucode_hdr.data_size, eax
|
||||
je next_microcode
|
||||
|
||||
; Then verify total size - sizeof header > data size
|
||||
mov ecx, [esi].ucode_hdr.total_size
|
||||
sub ecx, sizeof ucode_hdr
|
||||
cmp ecx, [esi].ucode_hdr.data_size
|
||||
jng next_microcode ; Jif extended header does not exist
|
||||
|
||||
; Set edi -> extended header
|
||||
mov edi, esi
|
||||
add edi, sizeof ucode_hdr
|
||||
add edi, [esi].ucode_hdr.data_size
|
||||
|
||||
; Get count of extended structures
|
||||
mov ecx, [edi].ext_sig_hdr.count
|
||||
|
||||
; Move pointer to first signature structure
|
||||
add edi, sizeof ext_sig_hdr
|
||||
|
||||
check_ext_sig:
|
||||
; Check if extended signature and platform ID match
|
||||
cmp [edi].ext_sig.processor, ebx
|
||||
jne @f
|
||||
test [edi].ext_sig.flags, edx
|
||||
jnz load_check ; Jif signature and platform ID match
|
||||
@@:
|
||||
; Check if any more extended signatures exist
|
||||
add edi, sizeof ext_sig
|
||||
loop check_ext_sig
|
||||
|
||||
next_microcode:
|
||||
; Advance just after end of this microcode
|
||||
xor eax, eax
|
||||
cmp [esi].ucode_hdr.total_size, eax
|
||||
je @f
|
||||
add esi, [esi].ucode_hdr.total_size
|
||||
jmp check_address
|
||||
@@:
|
||||
add esi, dword ptr 2048
|
||||
jmp check_address
|
||||
|
||||
advance_fixed_size:
|
||||
; Advance by 4X dwords
|
||||
add esi, dword ptr 1024
|
||||
|
||||
check_address:
|
||||
; Is valid Microcode start point ?
|
||||
cmp dword ptr [esi], 0ffffffffh
|
||||
jz done
|
||||
|
||||
; Address >= microcode region address + microcode region size?
|
||||
mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
|
||||
add eax, [esp].LOAD_UCODE_PARAMS.ucode_code_size
|
||||
cmp esi, eax
|
||||
jae done ;Jif address is outside of ucode region
|
||||
jmp check_main_header
|
||||
|
||||
load_check:
|
||||
; 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 [esi].ucode_hdr.revision, edx
|
||||
je continue
|
||||
|
||||
load_microcode:
|
||||
; 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, sizeof ucode_hdr
|
||||
xor edx, edx
|
||||
mov ecx, MSR_IA32_BIOS_UPDT_TRIG
|
||||
wrmsr
|
||||
mov eax, 1
|
||||
cpuid
|
||||
|
||||
continue:
|
||||
jmp next_microcode
|
||||
|
||||
done:
|
||||
mov eax, 1
|
||||
cpuid
|
||||
mov ecx, MSR_IA32_BIOS_SIGN_ID
|
||||
rdmsr ; Get current microcode signature
|
||||
xor eax, eax
|
||||
cmp edx, 0
|
||||
jnz exit
|
||||
mov eax, 08000000Eh
|
||||
|
||||
exit:
|
||||
jmp ebp
|
||||
|
||||
LoadUcodeDflt ENDP
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; 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.
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
TempRamInitApi PROC NEAR PUBLIC
|
||||
;
|
||||
; Ensure SSE is enabled
|
||||
;
|
||||
ENABLE_SSE
|
||||
|
||||
;
|
||||
; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
|
||||
;
|
||||
SAVE_REGS
|
||||
|
||||
;
|
||||
; Save timestamp into XMM4 & XMM5
|
||||
;
|
||||
rdtsc
|
||||
SAVE_EAX
|
||||
SAVE_EDX
|
||||
|
||||
;
|
||||
; Check Parameter
|
||||
;
|
||||
mov eax, dword ptr [esp + 4]
|
||||
cmp eax, 0
|
||||
mov eax, 80000002h
|
||||
jz NemInitExit
|
||||
|
||||
;
|
||||
; CPUID/DeviceID check
|
||||
;
|
||||
mov eax, @F
|
||||
jmp FspSelfCheck ; Note: ESP can not be changed.
|
||||
@@:
|
||||
cmp eax, 0
|
||||
jnz NemInitExit
|
||||
|
||||
;
|
||||
; Platform Basic Init.
|
||||
;
|
||||
mov eax, @F
|
||||
jmp PlatformBasicInit
|
||||
@@:
|
||||
cmp eax, 0
|
||||
jnz NemInitExit
|
||||
|
||||
;
|
||||
; Load microcode
|
||||
;
|
||||
mov eax, @F
|
||||
add esp, 4
|
||||
jmp LoadUcode
|
||||
@@:
|
||||
LOAD_ESP
|
||||
cmp eax, 0
|
||||
jnz NemInitExit
|
||||
|
||||
;
|
||||
; Call platform NEM init
|
||||
;
|
||||
mov eax, @F
|
||||
add esp, 4
|
||||
jmp PlatformTempRamInit
|
||||
@@:
|
||||
LOAD_ESP
|
||||
cmp eax, 0
|
||||
jnz NemInitExit
|
||||
|
||||
;
|
||||
; Save parameter pointer in edx
|
||||
;
|
||||
mov edx, dword ptr [esp + 4]
|
||||
|
||||
;
|
||||
; Enable FSP STACK
|
||||
;
|
||||
mov esp, PcdGet32(PcdTemporaryRamBase)
|
||||
add esp, PcdGet32(PcdTemporaryRamSize)
|
||||
|
||||
push DATA_LEN_OF_MCUD ; Size of the data region
|
||||
push 4455434Dh ; Signature of the data region 'MCUD'
|
||||
push dword ptr [edx + 4] ; Microcode size
|
||||
push dword ptr [edx + 0] ; Microcode base
|
||||
push dword ptr [edx + 12] ; Code size
|
||||
push dword ptr [edx + 8] ; Code base
|
||||
|
||||
;
|
||||
; 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_EAX
|
||||
LOAD_EDX
|
||||
push edx
|
||||
push eax
|
||||
|
||||
;
|
||||
; Terminator for the data on stack
|
||||
;
|
||||
push 0
|
||||
|
||||
;
|
||||
; Set ECX/EDX to the bootloader temporary memory range
|
||||
;
|
||||
mov ecx, PcdGet32(PcdTemporaryRamBase)
|
||||
mov edx, ecx
|
||||
add edx, PcdGet32(PcdTemporaryRamSize)
|
||||
sub edx, PcdGet32(PcdFspTemporaryRamSize)
|
||||
|
||||
xor eax, eax
|
||||
|
||||
NemInitExit:
|
||||
;
|
||||
; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
|
||||
;
|
||||
LOAD_REGS
|
||||
ret
|
||||
TempRamInitApi ENDP
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; FspInit API
|
||||
;
|
||||
; This FSP API will perform the processor and chipset initialization.
|
||||
; This API will not return. Instead, it transfers the control to the
|
||||
; ContinuationFunc provided in the parameter.
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
FspInitApi PROC NEAR PUBLIC
|
||||
;
|
||||
; Stack must be ready
|
||||
;
|
||||
push 087654321h
|
||||
pop eax
|
||||
cmp eax, 087654321h
|
||||
jz @F
|
||||
mov eax, 080000003h
|
||||
jmp exit
|
||||
|
||||
@@:
|
||||
;
|
||||
; Additional check
|
||||
;
|
||||
pushad
|
||||
push 1
|
||||
call FspApiCallingCheck
|
||||
add esp, 4
|
||||
mov dword ptr [esp + 4 * 7], eax
|
||||
popad
|
||||
cmp eax, 0
|
||||
jz @F
|
||||
jmp exit
|
||||
|
||||
@@:
|
||||
;
|
||||
; Store the address in FSP which will return control to the BL
|
||||
;
|
||||
push offset exit
|
||||
|
||||
;
|
||||
; 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 fword ptr [esp]
|
||||
|
||||
;
|
||||
; Setup new FSP stack
|
||||
;
|
||||
mov eax, esp
|
||||
mov esp, PcdGet32(PcdTemporaryRamBase)
|
||||
add esp, PcdGet32(PcdTemporaryRamSize)
|
||||
sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
|
||||
|
||||
;
|
||||
; Save the bootloader's stack pointer
|
||||
;
|
||||
push eax
|
||||
|
||||
;
|
||||
; Pass entry point of the PEI core
|
||||
;
|
||||
call GetFspBaseAddress
|
||||
mov edi, FspImageSizeOffset
|
||||
mov edi, DWORD PTR [eax + edi]
|
||||
add edi, eax
|
||||
sub edi, 20h
|
||||
add eax, DWORD PTR [edi]
|
||||
push eax
|
||||
|
||||
;
|
||||
; Pass BFV into the PEI Core
|
||||
; It uses relative address to calucate the actual boot FV base
|
||||
; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
|
||||
; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
|
||||
; they are different. The code below can handle both cases.
|
||||
;
|
||||
call GetFspBaseAddress
|
||||
mov edi, eax
|
||||
call GetBootFirmwareVolumeOffset
|
||||
add eax, edi
|
||||
push eax
|
||||
|
||||
;
|
||||
; Pass stack base and size into the PEI Core
|
||||
;
|
||||
mov eax, PcdGet32(PcdTemporaryRamBase)
|
||||
add eax, PcdGet32(PcdTemporaryRamSize)
|
||||
sub eax, PcdGet32(PcdFspTemporaryRamSize)
|
||||
push eax
|
||||
push PcdGet32(PcdFspTemporaryRamSize)
|
||||
|
||||
;
|
||||
; Pass Control into the PEI Core
|
||||
;
|
||||
call SecStartup
|
||||
|
||||
exit:
|
||||
ret
|
||||
|
||||
FspInitApi ENDP
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; NotifyPhase API
|
||||
;
|
||||
; This FSP API will notify the FSP about the different phases in the boot
|
||||
; process
|
||||
;
|
||||
;----------------------------------------------------------------------------
|
||||
NotifyPhaseApi PROC C PUBLIC
|
||||
;
|
||||
; Stack must be ready
|
||||
;
|
||||
push 087654321h
|
||||
pop eax
|
||||
cmp eax, 087654321h
|
||||
jz @F
|
||||
mov eax, 080000003h
|
||||
jmp err_exit
|
||||
|
||||
@@:
|
||||
;
|
||||
; Verify the calling condition
|
||||
;
|
||||
pushad
|
||||
push 2
|
||||
call FspApiCallingCheck
|
||||
add esp, 4
|
||||
mov dword ptr [esp + 4 * 7], eax
|
||||
popad
|
||||
|
||||
cmp eax, 0
|
||||
jz @F
|
||||
|
||||
;
|
||||
; Error return
|
||||
;
|
||||
err_exit:
|
||||
ret
|
||||
|
||||
@@:
|
||||
jmp Pei2LoaderSwitchStack
|
||||
|
||||
NotifyPhaseApi ENDP
|
||||
|
||||
|
||||
END
|
611
IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
Normal file
611
IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
Normal file
@@ -0,0 +1,611 @@
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Provide FSP API entry points.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#.INCLUDE "UcodeLoad.inc"
|
||||
|
||||
#
|
||||
# Following are fixed PCDs
|
||||
#
|
||||
|
||||
.equ MSR_IA32_PLATFORM_ID, 0x000000017
|
||||
.equ MSR_IA32_BIOS_UPDT_TRIG, 0x000000079
|
||||
.equ MSR_IA32_BIOS_SIGN_ID, 0x00000008b
|
||||
|
||||
ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase)
|
||||
ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize)
|
||||
ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
|
||||
ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspAreaSize)
|
||||
|
||||
|
||||
#
|
||||
# Following functions will be provided in C
|
||||
#
|
||||
#EXTERNDEF SecStartup:PROC
|
||||
#EXTERNDEF FspApiCallingCheck:PROC
|
||||
|
||||
#
|
||||
# Following functions will be provided in PlatformSecLib
|
||||
#
|
||||
#EXTERNDEF GetFspBaseAddress:PROC
|
||||
#EXTERNDEF GetBootFirmwareVolumeOffset:PROC
|
||||
#EXTERNDEF PlatformTempRamInit:PROC
|
||||
#EXTERNDEF Pei2LoaderSwitchStack:PROC
|
||||
#EXTERN FspSelfCheck(FspSelfCheckDflt):PROC
|
||||
#EXTERN PlatformBasicInit(PlatformBasicInitDflt):PROC
|
||||
|
||||
#
|
||||
# Define the data length that we saved on the stack top
|
||||
#
|
||||
.equ DATA_LEN_OF_PER0, 0x018
|
||||
.equ DATA_LEN_OF_MCUD, 0x018
|
||||
.equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
|
||||
|
||||
#
|
||||
# Define SSE macros
|
||||
#
|
||||
.macro ENABLE_SSE
|
||||
movl %cr4, %eax
|
||||
orl $0x00000600,%eax # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
|
||||
movl %eax,%cr4
|
||||
.endm
|
||||
|
||||
.macro SAVE_REGS
|
||||
movd %ebp, %xmm7
|
||||
pshufd $0x93, %xmm7, %xmm7
|
||||
movd %ebx, %xmm6
|
||||
por %xmm6, %xmm7
|
||||
pshufd $0x93, %xmm7, %xmm7
|
||||
movd %esi,%xmm6
|
||||
por %xmm6, %xmm7
|
||||
pshufd $0x93, %xmm7, %xmm7
|
||||
movd %edi, %xmm6
|
||||
por %xmm6, %xmm7
|
||||
movd %esp, %xmm6
|
||||
.endm
|
||||
|
||||
.macro LOAD_REGS
|
||||
movd %xmm6, %esp
|
||||
movd %xmm7, %edi
|
||||
pshufd $0x39,%xmm7, %xmm7
|
||||
movd %xmm7, %esi
|
||||
pshufd $0x39,%xmm7, %xmm7
|
||||
movd %xmm7, %ebx
|
||||
pshufd $0x39, %xmm7, %xmm7
|
||||
movd %xmm7, %ebp
|
||||
.endm
|
||||
|
||||
.macro LOAD_ESP
|
||||
movd %xmm6, %esp
|
||||
.endm
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
ASM_GLOBAL ASM_PFX(FspSelfCheckDflt)
|
||||
ASM_PFX(FspSelfCheckDflt):
|
||||
# Inputs:
|
||||
# eax -> 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
|
||||
movl %eax, %ebp
|
||||
xorl %eax, %eax
|
||||
exit:
|
||||
jmp *%ebp
|
||||
#FspSelfCheckDflt ENDP
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
ASM_GLOBAL ASM_PFX(PlatformBasicInitDflt)
|
||||
ASM_PFX(PlatformBasicInitDflt):
|
||||
# Inputs:
|
||||
# eax -> 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
|
||||
movl %eax, %ebp
|
||||
xorl %eax, %eax
|
||||
exit2:
|
||||
jmp *%ebp
|
||||
#PlatformBasicInitDflt ENDP
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
ASM_GLOBAL ASM_PFX(LoadUcode)
|
||||
ASM_PFX(LoadUcode):
|
||||
# Inputs:
|
||||
# esp -> LOAD_UCODE_PARAMS 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
|
||||
movl %eax, %ebp
|
||||
cmpl $0, %esp
|
||||
jz paramerror
|
||||
movl (%esp), %eax #dword ptr [] Parameter pointer
|
||||
cmpl $0, %eax
|
||||
jz paramerror
|
||||
movl %eax, %esp
|
||||
movl (%esp), %esi #LOAD_UCODE_PARAMS.ucode_code_addr
|
||||
cmpl $0, %esi
|
||||
jnz L0
|
||||
|
||||
paramerror:
|
||||
movl $0x080000002, %eax
|
||||
jmp exit4
|
||||
|
||||
movl (%esp), %esi #.LOAD_UCODE_PARAMS.ucode_code_addr
|
||||
|
||||
check_main_header:
|
||||
# Get processor signature and platform ID from the installed processor
|
||||
# and save into registers for later use
|
||||
# ebx = processor signature
|
||||
# edx = platform ID
|
||||
movl $1, %eax
|
||||
cpuid
|
||||
movl %eax, %ebx
|
||||
movl MSR_IA32_PLATFORM_ID, %ecx
|
||||
rdmsr
|
||||
movl %edx, %ecx
|
||||
#--------------------------------------------------------------------------------------------------------------------
|
||||
shrl $18, %ecx #($50-$32)
|
||||
andl $0x7, %ecx
|
||||
movl $1, %edx
|
||||
shll %cl,%edx
|
||||
|
||||
# Current register usage
|
||||
# esp -> stack with paramters
|
||||
# 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
|
||||
movl $1, %eax
|
||||
cmpl %eax, (%esi) #.ucode_hdr.version
|
||||
jne advance_fixed_size
|
||||
cmpl %eax, 0x18(%esi) #.ucode_hdr.loader
|
||||
jne advance_fixed_size
|
||||
|
||||
# Check if signature and plaform ID match
|
||||
#--------------------------------------------------------------------------------------------------------------------------
|
||||
cmpl 0x10(%esi), %ebx #(%esi).ucode_hdr.processor
|
||||
jne L0
|
||||
testl 0x1c(%esi) , %edx #(%esi).ucode_hdr.flags
|
||||
jnz load_check # Jif signature and platform ID match
|
||||
|
||||
L0:
|
||||
# Check if extended header exists
|
||||
# First check if total_size and data_size are valid
|
||||
xorl %eax, %eax
|
||||
cmpl %eax,0x24(%esi) #(%esi).ucode_hdr.total_size
|
||||
je next_microcode
|
||||
cmpl %eax,0x20(%esi) #(%esi) .ucode_hdr.data_size
|
||||
je next_microcode
|
||||
|
||||
# Then verify total size - sizeof header > data size
|
||||
movl 0x24(%esi), %ecx #(%esi).ucode_hdr.total_size
|
||||
subl $0x30, %ecx #sizeof ucode_hdr = 48
|
||||
cmpl 0x20(%esi), %ecx #(%esi).ucode_hdr.data_size
|
||||
jz load_check
|
||||
jb next_microcode # Jif extended header does not exist
|
||||
|
||||
# Check if total size fits in microcode region
|
||||
movl %esi , %edi
|
||||
addl 0x24(%esi), %edi # (%esi).ucode_hdr.total_size
|
||||
movl (%esp), %ecx # (%esp).LOAD_UCODE_PARAMS.ucode_code_addr
|
||||
addl 4(%esp), %ecx #.LOAD_UCODE_PARAMS.ucode_code_size
|
||||
cmpl %ecx , %edi
|
||||
xorl %eax, %eax
|
||||
ja exit4 # Jif address is outside of ucode region
|
||||
|
||||
# Set edi -> extended header
|
||||
movl %esi , %edi
|
||||
addl $0x30 , %edi #sizeof ucode_hdr = 48
|
||||
addl 0x20(%esi), %edi #%esi.ucode_hdr.data_size
|
||||
|
||||
# Get count of extended structures
|
||||
movl (%edi), %ecx #(%edi).ext_sig_hdr.count
|
||||
|
||||
# Move pointer to first signature structure
|
||||
addl $0x20, %edi # sizeof ext_sig_hdr = 20
|
||||
|
||||
check_ext_sig:
|
||||
# Check if extended signature and platform ID match
|
||||
cmpl %ebx, (%edi) #[edi].ext_sig.processor
|
||||
jne L1
|
||||
test %edx, 4(%edi) #[edi].ext_sig.flags
|
||||
jnz load_check # Jif signature and platform ID match
|
||||
L9:
|
||||
# Check if any more extended signatures exist
|
||||
addl $0xc, %edi #sizeof ext_sig = 12
|
||||
loop check_ext_sig
|
||||
|
||||
next_microcode:
|
||||
# Advance just after end of this microcode
|
||||
xorl %eax, %eax
|
||||
cmpl %eax, 0x24(%esi) #(%esi).ucode_hdr.total_size
|
||||
je L2
|
||||
add 0x24(%esi) , %esi #(%esi).ucode_hdr.total_size
|
||||
jmp check_address
|
||||
L10:
|
||||
addl $0x800, %esi
|
||||
jmp check_address
|
||||
|
||||
advance_fixed_size:
|
||||
# Advance by 4X dwords
|
||||
addl $0x400, %esi
|
||||
|
||||
check_address:
|
||||
# Is valid Microcode start point ?
|
||||
cmp $0x0ffffffff , %esi
|
||||
jz done
|
||||
|
||||
# Address >= microcode region address + microcode region size?
|
||||
movl (%esp), %eax #(%esp).LOAD_UCODE_PARAMS.ucode_code_addr
|
||||
addl 4(%esp), %eax #(%esp).LOAD_UCODE_PARAMS.ucode_code_size
|
||||
cmpl %eax, %esi
|
||||
jae done #Jif address is outside of ucode region
|
||||
jmp check_main_header
|
||||
|
||||
load_check:
|
||||
# Get the revision of the current microcode update loaded
|
||||
movl MSR_IA32_BIOS_SIGN_ID, %ecx
|
||||
xorl %eax, %eax # Clear EAX
|
||||
xorl %edx, %edx # Clear EDX
|
||||
wrmsr # Load 0 to MSR at 8Bh
|
||||
|
||||
movl $1, %eax
|
||||
cpuid
|
||||
movl MSR_IA32_BIOS_SIGN_ID, %ecx
|
||||
rdmsr # Get current microcode signature
|
||||
|
||||
# Verify this microcode update is not already loaded
|
||||
cmpl %edx, 4(%esi) #(%esi).ucode_hdr.revision
|
||||
je continue
|
||||
|
||||
load_microcode:
|
||||
# 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 %esi, %eax
|
||||
add $0x30, %eax #sizeof ucode_hdr = 48
|
||||
xorl %edx, %edx
|
||||
mov MSR_IA32_BIOS_UPDT_TRIG,%ecx
|
||||
wrmsr
|
||||
mov $1, %eax
|
||||
cpuid
|
||||
|
||||
continue:
|
||||
jmp next_microcode
|
||||
|
||||
done:
|
||||
mov $1, %eax
|
||||
cpuid
|
||||
mov MSR_IA32_BIOS_SIGN_ID, %ecx
|
||||
rdmsr # Get current microcode signature
|
||||
xorl %eax, %eax
|
||||
cmp $0 , %edx
|
||||
jnz exit4
|
||||
mov $0x08000000E, %eax
|
||||
|
||||
exit4:
|
||||
jmp *%ebp
|
||||
|
||||
#LoadUcode ENDP
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# 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.
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
ASM_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 XMM4 & XMM5
|
||||
#
|
||||
rdtsc
|
||||
movd %edx, %xmm4
|
||||
movd %eax, %xmm5
|
||||
|
||||
#
|
||||
# CPUID/DeviceID check
|
||||
#
|
||||
movl L11, %eax
|
||||
jmp ASM_PFX(FspSelfCheck) # Note: ESP can not be changed.
|
||||
L11:
|
||||
cmpl $0, %eax
|
||||
jnz NemInitExit
|
||||
|
||||
#
|
||||
# Platform Basic Init.
|
||||
#
|
||||
movl L1, %eax
|
||||
jmp ASM_PFX(PlatformBasicInitDflt)
|
||||
L1:
|
||||
cmp $0, %eax
|
||||
jnz NemInitExit
|
||||
|
||||
#
|
||||
# Load microcode
|
||||
#
|
||||
movl L2, %eax
|
||||
addl $4, %esp
|
||||
jmp LoadUcode
|
||||
L2:
|
||||
LOAD_ESP
|
||||
cmpl $0, %eax
|
||||
jnz NemInitExit
|
||||
|
||||
#
|
||||
# Call platform NEM init
|
||||
#-------------------------------------------------------------------------------------------------------------------------
|
||||
movl L3, %eax
|
||||
addl $4, %esp
|
||||
jmp ASM_PFX(PlatformTempRamInit)
|
||||
L3:
|
||||
subl $4, %esp
|
||||
cmpl $0, %eax
|
||||
jnz NemInitExit
|
||||
|
||||
#
|
||||
# Save parameter pointer in edx
|
||||
#
|
||||
movl 4(%esp), %edx
|
||||
|
||||
#
|
||||
# Enable FSP STACK
|
||||
#
|
||||
movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp
|
||||
addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %esp
|
||||
|
||||
pushl $DATA_LEN_OF_MCUD # Size of the data region
|
||||
pushl 0x4455434D # Signature of the data region 'MCUD'
|
||||
pushl 12(%edx) # Code size
|
||||
pushl 8(%edx) # Code base
|
||||
cmpl $0, %edx # Is parameter pointer valid ?
|
||||
jz InvalidMicrocodeRegion
|
||||
pushl 4(%edx) # Microcode size
|
||||
pushl (%edx) # Microcode base
|
||||
jmp L4
|
||||
|
||||
InvalidMicrocodeRegion:
|
||||
pushl $0 # Microcode size
|
||||
pushl $0 # Microcode base
|
||||
|
||||
L4:
|
||||
#
|
||||
# Save API entry/exit timestamp into stack
|
||||
#
|
||||
pushl DATA_LEN_OF_PER0 # Size of the data region
|
||||
pushl 0x30524550 # Signature of the data region 'PER0'
|
||||
movd %xmm4, %eax
|
||||
pushl %eax
|
||||
movd %xmm5, %eax
|
||||
pushl %eax
|
||||
rdtsc
|
||||
pushl %edx
|
||||
pushl %eax
|
||||
|
||||
#
|
||||
# Terminator for the data on stack
|
||||
#
|
||||
pushl $0
|
||||
|
||||
#
|
||||
# Set ECX/EDX to the bootloader temporary memory range
|
||||
#
|
||||
movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %ecx
|
||||
movl %ecx, %edx
|
||||
addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %edx
|
||||
subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %edx
|
||||
|
||||
xorl %eax, %eax
|
||||
|
||||
NemInitExit:
|
||||
#
|
||||
# Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
|
||||
#
|
||||
LOAD_REGS
|
||||
ret
|
||||
#TempRamInitApi ENDP
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# FspInit API
|
||||
#
|
||||
# This FSP API will perform the processor and chipset initialization.
|
||||
# This API will not return. Instead, it transfers the control to the
|
||||
# ContinuationFunc provided in the parameter.
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
ASM_GLOBAL ASM_PFX(FspInitApi)
|
||||
ASM_PFX(FspInitApi):
|
||||
#
|
||||
# Stack must be ready
|
||||
#
|
||||
pushl $0x087654321
|
||||
pop %eax
|
||||
cmpl $0x087654321, %eax
|
||||
jz L5
|
||||
movl $0x080000003, %eax
|
||||
jmp exit3
|
||||
|
||||
L5:
|
||||
#
|
||||
# Additional check
|
||||
#
|
||||
pusha
|
||||
pushl $1
|
||||
call ASM_PFX(FspApiCallingCheck)
|
||||
addl $4, %esp
|
||||
movl %eax, 28(%esp)
|
||||
popa
|
||||
cmpl $0 , %eax
|
||||
jz L6
|
||||
jmp exit3
|
||||
|
||||
L6:
|
||||
#
|
||||
# Save the Platform Data Pointer in EDI
|
||||
#
|
||||
movl 4(%esp), %edi
|
||||
|
||||
#
|
||||
# Store the address in FSP which will return control to the BL
|
||||
#
|
||||
pushl $exit3
|
||||
|
||||
#
|
||||
# Create a Task Frame in the stack for the Boot Loader
|
||||
#
|
||||
pushfl
|
||||
pushfl # 2 pushf for 4 byte alignment
|
||||
cli
|
||||
pushal
|
||||
|
||||
# Reserve 8 bytes for IDT save/restore
|
||||
pushl $0
|
||||
pushl $0
|
||||
sidt (%esp)
|
||||
|
||||
#
|
||||
# Setup new FSP stack
|
||||
#
|
||||
movl %esp, %eax
|
||||
movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp
|
||||
addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize) , %esp
|
||||
subl DATA_LEN_AT_STACK_TOP, %esp
|
||||
addl $0x0FFFFFFC0, %esp
|
||||
|
||||
#
|
||||
# Save the bootloader's stack pointer
|
||||
#
|
||||
pushl %eax
|
||||
|
||||
#
|
||||
# Pass entry point of the PEI core
|
||||
#
|
||||
call ASM_PFX(GetFspBaseAddress)
|
||||
movl %eax, %edi
|
||||
addl ASM_PFX(_gPcd_FixedAtBuild_PcdFspAreaSize), %edi
|
||||
subl $0x20, %edi
|
||||
addl %ds:(%edi), %eax
|
||||
pushl %eax
|
||||
|
||||
#
|
||||
# Pass BFV into the PEI Core
|
||||
# It uses relative address to calucate the actual boot FV base
|
||||
# For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
|
||||
# PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
|
||||
# they are different. The code below can handle both cases.
|
||||
#
|
||||
call ASM_PFX(GetFspBaseAddress)
|
||||
movl %eax , %edi
|
||||
call ASM_PFX(GetBootFirmwareVolumeOffset)
|
||||
addl %edi ,%eax
|
||||
pushl %eax
|
||||
|
||||
#
|
||||
# Pass stack base and size into the PEI Core
|
||||
#
|
||||
movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %eax
|
||||
addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %eax
|
||||
subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %eax
|
||||
pushl %eax
|
||||
pushl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
|
||||
|
||||
#
|
||||
# Pass Control into the PEI Core
|
||||
#
|
||||
call ASM_PFX(SecStartup)
|
||||
|
||||
exit3:
|
||||
ret
|
||||
|
||||
# FspInitApi ENDP
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# NotifyPhase API
|
||||
#
|
||||
# This FSP API will notify the FSP about the different phases in the boot
|
||||
# process
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
ASM_GLOBAL ASM_PFX(NotifyPhaseApi)
|
||||
ASM_PFX(NotifyPhaseApi):
|
||||
#
|
||||
# Stack must be ready
|
||||
#
|
||||
pushl $0x0087654321
|
||||
pop %eax
|
||||
cmpl $0x087654321, %eax
|
||||
jz L7
|
||||
movl $0x080000003, %eax
|
||||
jmp err_exit
|
||||
|
||||
L7:
|
||||
#
|
||||
# Verify the calling condition
|
||||
#
|
||||
pusha
|
||||
pushl $2
|
||||
call ASM_PFX(FspApiCallingCheck)
|
||||
add $4, %esp
|
||||
mov %eax, 28(%esp)
|
||||
popa
|
||||
|
||||
cmpl $0, %eax
|
||||
jz L8
|
||||
|
||||
#
|
||||
# Error return
|
||||
#
|
||||
err_exit:
|
||||
ret
|
||||
|
||||
L8:
|
||||
jmp ASM_PFX(Pei2LoaderSwitchStack)
|
||||
|
||||
#NotifyPhaseApi ENDP
|
||||
|
||||
|
||||
#END
|
79
IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm
Normal file
79
IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm
Normal file
@@ -0,0 +1,79 @@
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php.
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
.686
|
||||
.model flat,C
|
||||
.const
|
||||
;
|
||||
; Float control word initial value:
|
||||
; all exceptions masked, double-precision, round-to-nearest
|
||||
;
|
||||
mFpuControlWord DW 027Fh
|
||||
;
|
||||
; Multimedia-extensions control word:
|
||||
; all exceptions masked, round-to-nearest, flush to zero for masked underflow
|
||||
;
|
||||
mMmxControlWord DD 01F80h
|
||||
|
||||
.xmm
|
||||
.code
|
||||
|
||||
;
|
||||
; Initializes floating point units for requirement of UEFI specification.
|
||||
;
|
||||
; This function initializes floating-point control word to 0x027F (all exceptions
|
||||
; masked,double-precision, round-to-nearest) and multimedia-extensions control word
|
||||
; (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
|
||||
; for masked underflow).
|
||||
;
|
||||
InitializeFloatingPointUnits PROC PUBLIC
|
||||
|
||||
push ebx
|
||||
|
||||
;
|
||||
; Initialize floating point units
|
||||
;
|
||||
finit
|
||||
fldcw mFpuControlWord
|
||||
|
||||
;
|
||||
; Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test
|
||||
; whether the processor supports SSE instruction.
|
||||
;
|
||||
mov eax, 1
|
||||
cpuid
|
||||
bt edx, 25
|
||||
jnc Done
|
||||
|
||||
;
|
||||
; Set OSFXSR bit 9 in CR4
|
||||
;
|
||||
mov eax, cr4
|
||||
or eax, BIT9
|
||||
mov cr4, eax
|
||||
|
||||
;
|
||||
; The processor should support SSE instruction and we can use
|
||||
; ldmxcsr instruction
|
||||
;
|
||||
ldmxcsr mMmxControlWord
|
||||
Done:
|
||||
pop ebx
|
||||
|
||||
ret
|
||||
|
||||
InitializeFloatingPointUnits ENDP
|
||||
|
||||
END
|
73
IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s
Normal file
73
IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s
Normal file
@@ -0,0 +1,73 @@
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#
|
||||
# Float control word initial value:
|
||||
# all exceptions masked, double-precision, round-to-nearest
|
||||
#
|
||||
ASM_PFX(mFpuControlWord): .word 0x027F
|
||||
#
|
||||
# Multimedia-extensions control word:
|
||||
# all exceptions masked, round-to-nearest, flush to zero for masked underflow
|
||||
#
|
||||
ASM_PFX(mMmxControlWord): .long 0x01F80
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Initializes floating point units for requirement of UEFI specification.
|
||||
#
|
||||
# This function initializes floating-point control word to 0x027F (all exceptions
|
||||
# masked,double-precision, round-to-nearest) and multimedia-extensions control word
|
||||
# (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
|
||||
# for masked underflow).
|
||||
#
|
||||
ASM_GLOBAL ASM_PFX(InitializeFloatingPointUnits)
|
||||
ASM_PFX(InitializeFloatingPointUnits):
|
||||
|
||||
pushl %ebx
|
||||
|
||||
#
|
||||
# Initialize floating point units
|
||||
#
|
||||
finit
|
||||
fldcw ASM_PFX(mFpuControlWord)
|
||||
|
||||
#
|
||||
# Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test
|
||||
# whether the processor supports SSE instruction.
|
||||
#
|
||||
movl $1, %eax
|
||||
cpuid
|
||||
btl $25, %edx
|
||||
jnc Done
|
||||
|
||||
#
|
||||
# Set OSFXSR bit 9 in CR4
|
||||
#
|
||||
movl %cr4, %eax
|
||||
or BIT9, %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
#
|
||||
# The processor should support SSE instruction and we can use
|
||||
# ldmxcsr instruction
|
||||
#
|
||||
ldmxcsr ASM_PFX(mMmxControlWord)
|
||||
|
||||
Done:
|
||||
popl %ebx
|
||||
|
||||
ret
|
103
IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16
Normal file
103
IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16
Normal file
@@ -0,0 +1,103 @@
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php.
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Reset Vector Data structure
|
||||
; This structure is located at 0xFFFFFFC0
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
.model tiny
|
||||
.686p
|
||||
.stack 0h
|
||||
.code
|
||||
|
||||
;
|
||||
; The layout of this file is fixed. The build tool makes assumption of the layout.
|
||||
;
|
||||
|
||||
ORG 0h
|
||||
;
|
||||
; Reserved
|
||||
;
|
||||
ReservedData DD 0eeeeeeeeh, 0eeeeeeeeh
|
||||
|
||||
ORG 10h
|
||||
;
|
||||
; This is located at 0xFFFFFFD0h
|
||||
;
|
||||
mov di, "AP"
|
||||
jmp ApStartup
|
||||
|
||||
ORG 20h
|
||||
;
|
||||
; 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 12345678h
|
||||
|
||||
;
|
||||
; 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 PROC
|
||||
jmp $
|
||||
iret
|
||||
InterruptHandler ENDP
|
||||
|
||||
ORG 30h
|
||||
;
|
||||
; 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 relatvie address will be fixed up by some build tool.
|
||||
;
|
||||
; Typically, SEC entry point is the function _ModuleEntryPoint() defined in
|
||||
; SecEntry.asm
|
||||
;
|
||||
DB 0e9h
|
||||
DW -3
|
||||
|
||||
|
||||
ORG 38h
|
||||
;
|
||||
; 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 12345678h
|
||||
|
||||
ORG 3ch
|
||||
;
|
||||
; 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 12345678h
|
||||
|
||||
;
|
||||
; Nothing can go here, otherwise the layout of this file would change.
|
||||
;
|
||||
|
||||
END
|
103
IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc
Normal file
103
IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc
Normal file
@@ -0,0 +1,103 @@
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php.
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
; 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
|
||||
;
|
||||
SXMMN MACRO XMM, IDX, REG
|
||||
pinsrd XMM, REG, (IDX AND 3)
|
||||
ENDM
|
||||
|
||||
LXMMN MACRO XMM, REG, IDX
|
||||
pextrd REG, XMM, (IDX AND 3)
|
||||
ENDM
|
||||
ELSE
|
||||
;
|
||||
; Define SSE macros using SSE 2 instructions
|
||||
;
|
||||
SXMMN MACRO XMM, IDX, REG
|
||||
pinsrw XMM, REG, (IDX AND 3) * 2
|
||||
ror REG, 16
|
||||
pinsrw XMM, REG, (IDX AND 3) * 2 + 1
|
||||
rol REG, 16
|
||||
ENDM
|
||||
|
||||
LXMMN MACRO XMM, REG, IDX
|
||||
pshufd XMM, XMM, (0E4E4E4h SHR (IDX * 2)) AND 0FFh
|
||||
movd REG, XMM
|
||||
pshufd XMM, XMM, (0E4E4E4h SHR (IDX * 2 + (IDX AND 1) * 4)) AND 0FFh
|
||||
ENDM
|
||||
ENDIF
|
||||
|
||||
|
||||
SAVE_REGS MACRO
|
||||
SXMMN xmm7, 0, ebp
|
||||
SXMMN xmm7, 1, ebx
|
||||
SXMMN xmm7, 2, esi
|
||||
SXMMN xmm7, 3, edi
|
||||
SAVE_ESP
|
||||
ENDM
|
||||
|
||||
LOAD_REGS MACRO
|
||||
LXMMN xmm7, ebp, 0
|
||||
LXMMN xmm7, ebx, 1
|
||||
LXMMN xmm7, esi, 2
|
||||
LXMMN xmm7, edi, 3
|
||||
LOAD_ESP
|
||||
ENDM
|
||||
|
||||
LOAD_EAX MACRO
|
||||
LXMMN xmm6, eax, 1
|
||||
ENDM
|
||||
|
||||
SAVE_EAX MACRO
|
||||
SXMMN xmm6, 1, eax
|
||||
ENDM
|
||||
|
||||
LOAD_EDX MACRO
|
||||
LXMMN xmm6, edx, 2
|
||||
ENDM
|
||||
|
||||
SAVE_EDX MACRO
|
||||
SXMMN xmm6, 2, edx
|
||||
ENDM
|
||||
|
||||
SAVE_ECX MACRO
|
||||
SXMMN xmm6, 3, ecx
|
||||
ENDM
|
||||
|
||||
LOAD_ECX MACRO
|
||||
LXMMN xmm6, ecx, 3
|
||||
ENDM
|
||||
|
||||
SAVE_ESP MACRO
|
||||
SXMMN xmm6, 0, esp
|
||||
ENDM
|
||||
|
||||
LOAD_ESP MACRO
|
||||
movd esp, xmm6
|
||||
ENDM
|
||||
|
||||
ENABLE_SSE MACRO
|
||||
mov eax, cr4
|
||||
or eax, 00000600h
|
||||
mov cr4, eax
|
||||
ENDM
|
82
IntelFspPkg/FspSecCore/Ia32/Stack.asm
Normal file
82
IntelFspPkg/FspSecCore/Ia32/Stack.asm
Normal file
@@ -0,0 +1,82 @@
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php.
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Switch the stack from temporary memory to permenent memory.
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
.586p
|
||||
.model flat,C
|
||||
.code
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; VOID
|
||||
; EFIAPI
|
||||
; SecSwitchStack (
|
||||
; UINT32 TemporaryMemoryBase,
|
||||
; UINT32 PermenentMemoryBase
|
||||
; );
|
||||
;------------------------------------------------------------------------------
|
||||
SecSwitchStack PROC
|
||||
;
|
||||
; 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 permenent
|
||||
; 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 permenent memory at first.
|
||||
; Then, Fixup the esp point to permenent memory
|
||||
;
|
||||
mov eax, esp
|
||||
sub eax, ebx
|
||||
add eax, ecx
|
||||
mov edx, dword ptr [esp] ; copy pushed register's value to permenent memory
|
||||
mov dword ptr [eax], edx
|
||||
mov edx, dword ptr [esp + 4]
|
||||
mov dword ptr [eax + 4], edx
|
||||
mov edx, dword ptr [esp + 8]
|
||||
mov dword ptr [eax + 8], edx
|
||||
mov edx, dword ptr [esp + 12]
|
||||
mov dword ptr [eax + 12], edx
|
||||
mov edx, dword ptr [esp + 16] ; Update this function's return address into permenent memory
|
||||
mov dword ptr [eax + 16], edx
|
||||
mov esp, eax ; From now, esp is pointed to permenent memory
|
||||
|
||||
;
|
||||
; Fixup the ebp point to permenent memory
|
||||
;
|
||||
mov eax, ebp
|
||||
sub eax, ebx
|
||||
add eax, ecx
|
||||
mov ebp, eax ; From now, ebp is pointed to permenent memory
|
||||
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
pop eax
|
||||
ret
|
||||
SecSwitchStack ENDP
|
||||
|
||||
END
|
88
IntelFspPkg/FspSecCore/Ia32/Stacks.s
Normal file
88
IntelFspPkg/FspSecCore/Ia32/Stacks.s
Normal file
@@ -0,0 +1,88 @@
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php.
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Switch the stack from temporary memory to permenent memory.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(SecSwitchStack)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# VOID
|
||||
# EFIAPI
|
||||
# SecSwitchStack (
|
||||
# UINT32 TemporaryMemoryBase,
|
||||
# UINT32 PermenentMemoryBase
|
||||
# )
|
||||
#------------------------------------------------------------------------------
|
||||
ASM_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 permenent
|
||||
# memory at first!
|
||||
#
|
||||
|
||||
movl 20(%esp), %ebx # Save the first parameter
|
||||
movl 24(%esp), %ecx # Save the second parameter
|
||||
|
||||
#
|
||||
# Save this function's return address into permenent memory at first.
|
||||
# Then, Fixup the esp point to permenent memory
|
||||
#
|
||||
|
||||
movl %esp, %eax
|
||||
subl %ebx, %eax
|
||||
addl %ecx, %eax
|
||||
movl (%esp), %edx # copy pushed register's value to permenent memory
|
||||
movl %edx, (%eax)
|
||||
movl 4(%esp), %edx
|
||||
movl %edx, 4(%eax)
|
||||
movl 8(%esp), %edx
|
||||
movl %edx, 8(%eax)
|
||||
movl 12(%esp), %edx
|
||||
movl %edx, 12(%eax)
|
||||
movl 16(%esp), %edx # Update this function's return address into permenent memory
|
||||
movl %edx, 16(%eax)
|
||||
movl %eax, %esp # From now, esp is pointed to permenent memory
|
||||
|
||||
#
|
||||
# Fixup the ebp point to permenent memory
|
||||
#
|
||||
|
||||
movl %ebp, %eax
|
||||
subl %ebx, %eax
|
||||
addl %ecx, %eax
|
||||
movl %eax, %ebp # From now, ebp is pointed to permenent memory
|
||||
|
||||
#
|
||||
# Fixup callee's ebp point for PeiDispatch
|
||||
#
|
||||
movl %ebp, %eax
|
||||
subl %ebx, %eax
|
||||
addl %ecx, %eax
|
||||
movl %eax, %ebp # From now, ebp is pointed to permenent memory
|
||||
|
||||
pop %edx
|
||||
pop %ecx
|
||||
pop %ebx
|
||||
pop %eax
|
||||
ret
|
63
IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc
Normal file
63
IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc
Normal file
@@ -0,0 +1,63 @@
|
||||
;------------------------------------------------------------------------------
|
||||
;
|
||||
; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php.
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
MSR_IA32_PLATFORM_ID EQU 000000017h
|
||||
MSR_IA32_BIOS_UPDT_TRIG EQU 000000079h
|
||||
MSR_IA32_BIOS_SIGN_ID EQU 00000008bh
|
||||
|
||||
ucode STRUCT 1t
|
||||
version DWORD ?
|
||||
revision DWORD ?
|
||||
date DWORD ?
|
||||
processor DWORD ?
|
||||
checksum DWORD ?
|
||||
loader DWORD ?
|
||||
rsvd DWORD 6t DUP (?)
|
||||
data DWORD 500t DUP (?)
|
||||
ucode ENDS
|
||||
ucode_t TYPEDEF ucode
|
||||
|
||||
ucode_hdr STRUCT 1t
|
||||
version DWORD ?
|
||||
revision DWORD ?
|
||||
date DWORD ?
|
||||
processor DWORD ?
|
||||
checksum DWORD ?
|
||||
loader DWORD ?
|
||||
flags DWORD ?
|
||||
data_size DWORD ?
|
||||
total_size DWORD ?
|
||||
rsvd DWORD 3t DUP (?)
|
||||
ucode_hdr ENDS
|
||||
ucode_hdr_t TYPEDEF ucode_hdr
|
||||
|
||||
ext_sig_hdr STRUCT 1t
|
||||
count DWORD ?
|
||||
checksum DWORD ?
|
||||
rsvd DWORD 3t DUP (?)
|
||||
ext_sig_hdr ENDS
|
||||
ext_sig_hdr_t TYPEDEF ext_sig_hdr
|
||||
|
||||
ext_sig STRUCT 1t
|
||||
processor DWORD ?
|
||||
flags DWORD ?
|
||||
checksum DWORD ?
|
||||
ext_sig ENDS
|
||||
ext_sig_t TYPEDEF ext_sig
|
||||
|
||||
LOAD_UCODE_PARAMS STRUCT 1t
|
||||
ucode_code_addr DWORD ?
|
||||
ucode_code_size DWORD ?
|
||||
LOAD_UCODE_PARAMS ENDS
|
268
IntelFspPkg/FspSecCore/SecFsp.c
Normal file
268
IntelFspPkg/FspSecCore/SecFsp.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "SecFsp.h"
|
||||
|
||||
UINT32 FspImageSizeOffset = FSP_INFO_HEADER_OFF + OFFSET_IN_FSP_INFO_HEADER(ImageSize);
|
||||
|
||||
/**
|
||||
|
||||
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 *)(GetFspBaseAddress() + FSP_INFO_HEADER_OFF);
|
||||
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 function gets the FSP UPD region offset in flash.
|
||||
|
||||
@return the offset of the UPD region.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
EFIAPI
|
||||
GetFspUpdRegionOffset (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
FSP_GLOBAL_DATA *FspData;
|
||||
UINT32 *Offset;
|
||||
|
||||
FspData = GetFspGlobalDataPointer ();
|
||||
|
||||
//
|
||||
// It is required to put PcdUpdRegionOffset at offset 0x000C
|
||||
// for all FSPs.
|
||||
// gPlatformFspPkgTokenSpaceGuid.PcdUpdRegionOffset | 0x000C | 0x12345678
|
||||
//
|
||||
Offset = (UINT32 *)(FspData->FspInfoHeader->ImageBase + \
|
||||
FspData->FspInfoHeader->CfgRegionOffset + 0x0C);
|
||||
|
||||
return *Offset;
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
//
|
||||
TopOfCar = PcdGet32 (PcdTemporaryRamBase) + PcdGet32 (PcdTemporaryRamSize);
|
||||
|
||||
FspPlatformData->DataPtr = NULL;
|
||||
FspPlatformData->CodeRegionSize = 0;
|
||||
FspPlatformData->CodeRegionBase = 0;
|
||||
FspPlatformData->MicorcodeRegionBase = 0;
|
||||
FspPlatformData->MicorcodeRegionSize = 0;
|
||||
|
||||
//
|
||||
// Pointer to the size field
|
||||
//
|
||||
StackPtr = (UINT32 *)(TopOfCar - sizeof(UINT32));
|
||||
|
||||
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->CodeRegionBase), 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_TMPRAMINIT_ENTRY;
|
||||
((UINT8 *)(&FspData->PerfData[1]))[7] = FSP_PERF_ID_API_TMPRAMINIT_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] BootFirmwareVolume Point to the address of BootFirmwareVolume in stack.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FspGlobalDataInit (
|
||||
IN OUT FSP_GLOBAL_DATA *PeiFspData,
|
||||
IN VOID **BootFirmwareVolume
|
||||
)
|
||||
{
|
||||
VOID *UpdDataRgnPtr;
|
||||
FSP_INIT_PARAMS *FspInitParams;
|
||||
CHAR8 ImageId[9];
|
||||
UINTN Idx;
|
||||
|
||||
//
|
||||
// Init PCIE_BAR with value and set global FSP data pointer.
|
||||
// PciExpress Base should have been programmed by platform already.
|
||||
//
|
||||
SetFspGlobalDataPointer (PeiFspData);
|
||||
ZeroMem ((VOID *)PeiFspData, sizeof(FSP_GLOBAL_DATA));
|
||||
|
||||
PeiFspData->Signature = FSP_GLOBAL_DATA_SIGNATURE;
|
||||
PeiFspData->CoreStack = *(UINTN *)(BootFirmwareVolume + 2);
|
||||
PeiFspData->PerfIdx = 2;
|
||||
|
||||
SetFspMeasurePoint (FSP_PERF_ID_API_FSPINIT_ENTRY);
|
||||
|
||||
//
|
||||
// Get FSP Header offset
|
||||
// It may have multiple FVs, so look into the last one for FSP header
|
||||
//
|
||||
PeiFspData->FspInfoHeader = (FSP_INFO_HEADER *)(GetFspBaseAddress() + FSP_INFO_HEADER_OFF);
|
||||
SecGetPlatformData (PeiFspData);
|
||||
|
||||
//
|
||||
// Initialize UPD pointer.
|
||||
//
|
||||
FspInitParams = (FSP_INIT_PARAMS *)GetFspApiParameter ();
|
||||
UpdDataRgnPtr = ((FSP_INIT_RT_COMMON_BUFFER *)FspInitParams->RtBufferPtr)->UpdDataRgnPtr;
|
||||
if (UpdDataRgnPtr == NULL) {
|
||||
UpdDataRgnPtr = (VOID *)(PeiFspData->FspInfoHeader->ImageBase + GetFspUpdRegionOffset());
|
||||
}
|
||||
SetFspUpdDataPointer (UpdDataRgnPtr);
|
||||
|
||||
//
|
||||
// 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 golbal 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============= PEIM FSP (%a 0x%08X) =============\n", \
|
||||
ImageId, PeiFspData->FspInfoHeader->ImageRevision));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
This function check the FSP API calling condition.
|
||||
|
||||
@param[in] ApiIdx Internal index of the FSP API.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FspApiCallingCheck (
|
||||
UINT32 ApiIdx
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
FSP_GLOBAL_DATA *FspData;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
FspData = GetFspGlobalDataPointer ();
|
||||
if (ApiIdx == 1) {
|
||||
//
|
||||
// FspInit check
|
||||
//
|
||||
if ((UINT32)FspData != 0xFFFFFFFF) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
} else if (ApiIdx == 2) {
|
||||
//
|
||||
// NotifyPhase check
|
||||
//
|
||||
if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
} else {
|
||||
if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
97
IntelFspPkg/FspSecCore/SecFsp.h
Normal file
97
IntelFspPkg/FspSecCore/SecFsp.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SEC_FSP_H_
|
||||
#define _SEC_FSPE_H_
|
||||
|
||||
#include <PiPei.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 <FspApi.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] BootFirmwareVolume Point to the address of BootFirmwareVolume in stack.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FspGlobalDataInit (
|
||||
IN OUT FSP_GLOBAL_DATA *PeiFspData,
|
||||
IN VOID **BootFirmwareVolume
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
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
|
||||
GetFspBaseAddress (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
This function gets the FSP UPD region offset in flash.
|
||||
|
||||
@return the offset of the UPD region.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
EFIAPI
|
||||
GetFspUpdRegionOffset (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
208
IntelFspPkg/FspSecCore/SecMain.c
Normal file
208
IntelFspPkg/FspSecCore/SecMain.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "SecMain.h"
|
||||
#include "SecFsp.h"
|
||||
|
||||
EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
|
||||
SecTemporaryRamSupport
|
||||
};
|
||||
|
||||
EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
|
||||
{
|
||||
(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 tempory ram
|
||||
@param[in] BootFirmwareVolume Base address of the Boot Firmware Volume.
|
||||
|
||||
@return This function never returns.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SecStartup (
|
||||
IN UINT32 SizeOfRam,
|
||||
IN UINT32 TempRamBase,
|
||||
IN VOID *BootFirmwareVolume
|
||||
)
|
||||
{
|
||||
EFI_SEC_PEI_HAND_OFF SecCoreData;
|
||||
IA32_DESCRIPTOR IdtDescriptor;
|
||||
SEC_IDT_TABLE IdtTableInStack;
|
||||
UINT32 Index;
|
||||
FSP_GLOBAL_DATA PeiFspData;
|
||||
PEI_CORE_ENTRY PeiCore;
|
||||
UINT64 ExceptionHandler;
|
||||
|
||||
//
|
||||
// Process all libraries constructor function linked to SecCore.
|
||||
//
|
||||
ProcessLibraryConstructorList ();
|
||||
|
||||
//
|
||||
// Initialize floating point operating environment
|
||||
// to be compliant with UEFI spec.
|
||||
//
|
||||
InitializeFloatingPointUnits ();
|
||||
|
||||
|
||||
// |-------------------|---->
|
||||
// |Idt Table |
|
||||
// |-------------------|
|
||||
// |PeiService Pointer | PeiStackSize
|
||||
// |-------------------|
|
||||
// | |
|
||||
// | Stack |
|
||||
// |-------------------|---->
|
||||
// | |
|
||||
// | |
|
||||
// | Heap | PeiTemporayRamSize
|
||||
// | |
|
||||
// | |
|
||||
// |-------------------|----> TempRamBase
|
||||
IdtTableInStack.PeiService = NULL;
|
||||
ExceptionHandler = FspGetExceptionHandler(mIdtEntryTemplate);
|
||||
for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
|
||||
CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&ExceptionHandler, sizeof (UINT64));
|
||||
}
|
||||
|
||||
IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;
|
||||
IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
|
||||
|
||||
AsmWriteIdtr (&IdtDescriptor);
|
||||
|
||||
//
|
||||
// Iniitalize the global FSP data region
|
||||
//
|
||||
FspGlobalDataInit (&PeiFspData, &BootFirmwareVolume);
|
||||
|
||||
//
|
||||
// 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;
|
||||
SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;
|
||||
SecCoreData.TemporaryRamSize = SizeOfRam;
|
||||
SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
|
||||
SecCoreData.PeiTemporaryRamSize = SizeOfRam >> 1;
|
||||
SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);
|
||||
SecCoreData.StackSize = SizeOfRam >> 1;
|
||||
|
||||
//
|
||||
// Call PeiCore Entry
|
||||
//
|
||||
PeiCore = (PEI_CORE_ENTRY)(*(UINTN *)((&BootFirmwareVolume) + 1));
|
||||
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;
|
||||
|
||||
OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
|
||||
NewHeap = (VOID*)((UINTN)PermanentMemoryBase + CopySize / 2);
|
||||
|
||||
OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize / 2);
|
||||
NewStack = (VOID*)(UINTN)PermanentMemoryBase;
|
||||
|
||||
//
|
||||
// Migrate Heap
|
||||
//
|
||||
CopyMem (NewHeap, OldHeap, CopySize / 2);
|
||||
|
||||
//
|
||||
// Migrate Stack
|
||||
//
|
||||
CopyMem (NewStack, OldStack, CopySize / 2);
|
||||
|
||||
|
||||
//
|
||||
// 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
|
||||
// immediatly, also we need fixup the stack change caused by new call into
|
||||
// permenent memory.
|
||||
//
|
||||
SecSwitchStack (
|
||||
(UINT32) (UINTN) OldStack,
|
||||
(UINT32) (UINTN) NewStack
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
134
IntelFspPkg/FspSecCore/SecMain.h
Normal file
134
IntelFspPkg/FspSecCore/SecMain.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php.
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#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 <FspApi.h>
|
||||
|
||||
#define SEC_IDT_ENTRY_COUNT 34
|
||||
|
||||
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 {
|
||||
EFI_PEI_SERVICES *PeiService;
|
||||
UINT64 IdtTable[SEC_IDT_ENTRY_COUNT];
|
||||
} 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
|
||||
);
|
||||
|
||||
/**
|
||||
Initializes floating point units for requirement of UEFI specification.
|
||||
|
||||
This function initializes floating-point control word to 0x027F (all exceptions
|
||||
masked,double-precision, round-to-nearest) and multimedia-extensions control word
|
||||
(if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
|
||||
for masked underflow).
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
InitializeFloatingPointUnits (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
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 tempory ram
|
||||
@param[in] BootFirmwareVolume Base address of the Boot Firmware Volume.
|
||||
|
||||
@return This function never returns.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SecStartup (
|
||||
IN UINT32 SizeOfRam,
|
||||
IN UINT32 TempRamBase,
|
||||
IN VOID *BootFirmwareVolume
|
||||
);
|
||||
|
||||
/**
|
||||
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
|
||||
);
|
||||
|
||||
#endif
|
BIN
IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
Normal file
BIN
IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
Normal file
Binary file not shown.
53
IntelFspPkg/FspSecCore/Vtf0/Build.py
Normal file
53
IntelFspPkg/FspSecCore/Vtf0/Build.py
Normal file
@@ -0,0 +1,53 @@
|
||||
## @file
|
||||
# Automate the process of building the various reset vector types
|
||||
#
|
||||
# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
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)
|
||||
|
103
IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16
Normal file
103
IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16
Normal file
@@ -0,0 +1,103 @@
|
||||
;; @file
|
||||
; Reset Vector Data structure
|
||||
; This structure is located at 0xFFFFFFC0
|
||||
;
|
||||
; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php.
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
;;
|
||||
|
||||
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 relatvie 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
|
17
IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm
Normal file
17
IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm
Normal file
@@ -0,0 +1,17 @@
|
||||
;------------------------------------------------------------------------------
|
||||
; @file
|
||||
; This file includes all other code files to assemble the reset vector code
|
||||
;
|
||||
; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
|
||||
%include "Ia16/ResetVec.asm16"
|
110
IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py
Normal file
110
IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py
Normal file
@@ -0,0 +1,110 @@
|
||||
## @file
|
||||
# Apply fixup to VTF binary image for FFS Raw section
|
||||
#
|
||||
# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
|
||||
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()
|
||||
|
Reference in New Issue
Block a user