summaryrefslogtreecommitdiffstats
path: root/IntelFspPkg/FspSecCore
diff options
context:
space:
mode:
authorjyao1 <jyao1>2014-07-29 02:21:52 +0000
committerjyao1 <jyao1@6f19259b-4bc3-4df7-8a09-765794883524>2014-07-29 02:21:52 +0000
commitc8ec22a266cdd134ac99c3021003710130613a40 (patch)
tree39331503cf2a18089c025d466d3dd8d3b31e36c3 /IntelFspPkg/FspSecCore
parent0d807dae4adf222ee0c1b3abe504c9a271a46062 (diff)
downloadedk2-c8ec22a266cdd134ac99c3021003710130613a40.tar.gz
edk2-c8ec22a266cdd134ac99c3021003710130613a40.tar.bz2
edk2-c8ec22a266cdd134ac99c3021003710130613a40.zip
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
Diffstat (limited to 'IntelFspPkg/FspSecCore')
-rw-r--r--IntelFspPkg/FspSecCore/FspSecCore.inf76
-rw-r--r--IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm552
-rw-r--r--IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s611
-rw-r--r--IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm79
-rw-r--r--IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s73
-rw-r--r--IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16103
-rw-r--r--IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc103
-rw-r--r--IntelFspPkg/FspSecCore/Ia32/Stack.asm82
-rw-r--r--IntelFspPkg/FspSecCore/Ia32/Stacks.s88
-rw-r--r--IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc63
-rw-r--r--IntelFspPkg/FspSecCore/SecFsp.c268
-rw-r--r--IntelFspPkg/FspSecCore/SecFsp.h97
-rw-r--r--IntelFspPkg/FspSecCore/SecMain.c208
-rw-r--r--IntelFspPkg/FspSecCore/SecMain.h134
-rw-r--r--IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.rawbin0 -> 68 bytes
-rw-r--r--IntelFspPkg/FspSecCore/Vtf0/Build.py53
-rw-r--r--IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16103
-rw-r--r--IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm17
-rw-r--r--IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py110
19 files changed, 2820 insertions, 0 deletions
diff --git a/IntelFspPkg/FspSecCore/FspSecCore.inf b/IntelFspPkg/FspSecCore/FspSecCore.inf
new file mode 100644
index 0000000000..d3ec2fc64f
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/FspSecCore.inf
@@ -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
+
diff --git a/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
new file mode 100644
index 0000000000..8ad9744ab4
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
@@ -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
diff --git a/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
new file mode 100644
index 0000000000..433ef921c4
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
@@ -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
diff --git a/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm b/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm
new file mode 100644
index 0000000000..07f504da4b
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.asm
@@ -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
diff --git a/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s b/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s
new file mode 100644
index 0000000000..cfec8d7df5
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Ia32/InitializeFpu.s
@@ -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
diff --git a/IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16 b/IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16
new file mode 100644
index 0000000000..f77c9a46dd
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Ia32/ResetVec.asm16
@@ -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
diff --git a/IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc b/IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc
new file mode 100644
index 0000000000..a3d5c47ffa
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Ia32/SaveRestoreSse.inc
@@ -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
diff --git a/IntelFspPkg/FspSecCore/Ia32/Stack.asm b/IntelFspPkg/FspSecCore/Ia32/Stack.asm
new file mode 100644
index 0000000000..f96a55f040
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Ia32/Stack.asm
@@ -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
diff --git a/IntelFspPkg/FspSecCore/Ia32/Stacks.s b/IntelFspPkg/FspSecCore/Ia32/Stacks.s
new file mode 100644
index 0000000000..6c36c25d2b
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Ia32/Stacks.s
@@ -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 \ No newline at end of file
diff --git a/IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc b/IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc
new file mode 100644
index 0000000000..6be6ed097b
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Ia32/UcodeLoad.inc
@@ -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
diff --git a/IntelFspPkg/FspSecCore/SecFsp.c b/IntelFspPkg/FspSecCore/SecFsp.c
new file mode 100644
index 0000000000..00eb224c6f
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/SecFsp.c
@@ -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;
+}
diff --git a/IntelFspPkg/FspSecCore/SecFsp.h b/IntelFspPkg/FspSecCore/SecFsp.h
new file mode 100644
index 0000000000..9e129e4d5d
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/SecFsp.h
@@ -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
diff --git a/IntelFspPkg/FspSecCore/SecMain.c b/IntelFspPkg/FspSecCore/SecMain.c
new file mode 100644
index 0000000000..22706c8a8b
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/SecMain.c
@@ -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;
+}
diff --git a/IntelFspPkg/FspSecCore/SecMain.h b/IntelFspPkg/FspSecCore/SecMain.h
new file mode 100644
index 0000000000..4dfbc850b3
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/SecMain.h
@@ -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
diff --git a/IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw b/IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
new file mode 100644
index 0000000000..2dc9f178d3
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
Binary files differ
diff --git a/IntelFspPkg/FspSecCore/Vtf0/Build.py b/IntelFspPkg/FspSecCore/Vtf0/Build.py
new file mode 100644
index 0000000000..3018391445
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Vtf0/Build.py
@@ -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)
+
diff --git a/IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16 b/IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16
new file mode 100644
index 0000000000..585876fa86
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16
@@ -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
diff --git a/IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm b/IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm
new file mode 100644
index 0000000000..72b252491f
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Vtf0/ResetVectorCode.asm
@@ -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"
diff --git a/IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py b/IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py
new file mode 100644
index 0000000000..8e7c20b401
--- /dev/null
+++ b/IntelFspPkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py
@@ -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()
+