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:
jyao1
2014-07-29 02:21:52 +00:00
committed by jyao1
parent 0d807dae4a
commit c8ec22a266
64 changed files with 8155 additions and 0 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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;
}

View 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

View 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;
}

View 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

Binary file not shown.

View 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)

View 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

View 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"

View 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()