mirror of https://github.com/acidanthera/audk.git
814 lines
21 KiB
ArmAsm
814 lines
21 KiB
ArmAsm
#------------------------------------------------------------------------------
|
|
#
|
|
# Copyright (c) 2014 - 2015, 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.
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
|
|
|
|
.equ MSR_IA32_PLATFORM_ID, 0x00000017
|
|
.equ MSR_IA32_BIOS_UPDT_TRIG, 0x00000079
|
|
.equ MSR_IA32_BIOS_SIGN_ID, 0x0000008b
|
|
|
|
|
|
MicrocodeHdr:
|
|
.equ MicrocodeHdrVersion, 0x0000
|
|
.equ MicrocodeHdrRevision, 0x0004
|
|
.equ MicrocodeHdrDate, 0x0008
|
|
.equ MicrocodeHdrProcessor, 0x000c
|
|
.equ MicrocodeHdrChecksum, 0x0010
|
|
.equ MicrocodeHdrLoader, 0x0014
|
|
.equ MicrocodeHdrFlags, 0x0018
|
|
.equ MicrocodeHdrDataSize, 0x001C
|
|
.equ MicrocodeHdrTotalSize, 0x0020
|
|
.equ MicrocodeHdrRsvd, 0x0024
|
|
MicrocodeHdrEnd:
|
|
.equ MicrocodeHdrLength, 0x0030 # MicrocodeHdrLength = MicrocodeHdrEnd - MicrocodeHdr
|
|
|
|
|
|
ExtSigHdr:
|
|
.equ ExtSigHdrCount, 0x0000
|
|
.equ ExtSigHdrChecksum, 0x0004
|
|
.equ ExtSigHdrRsvd, 0x0008
|
|
ExtSigHdrEnd:
|
|
.equ ExtSigHdrLength, 0x0014 #ExtSigHdrLength = ExtSigHdrEnd - ExtSigHdr
|
|
|
|
ExtSig:
|
|
.equ ExtSigProcessor, 0x0000
|
|
.equ ExtSigFlags, 0x0004
|
|
.equ ExtSigChecksum, 0x0008
|
|
ExtSigEnd:
|
|
.equ ExtSigLength, 0x000C #ExtSigLength = ExtSigEnd - ExtSig
|
|
|
|
LoadMicrocodeParams:
|
|
.equ MicrocodeCodeAddr, 0x0000
|
|
.equ MicrocodeCodeSize, 0x0004
|
|
LoadMicrocodeParamsEnd:
|
|
|
|
|
|
|
|
.macro SAVE_REGS
|
|
pinsrw $0x00, %ebp, %xmm7
|
|
ror $0x10, %ebp
|
|
pinsrw $0x01, %ebp, %xmm7
|
|
ror $0x10, %ebp
|
|
#
|
|
pinsrw $0x02, %ebx, %xmm7
|
|
ror $0x10, %ebx
|
|
pinsrw $0x03, %ebx, %xmm7
|
|
ror $0x10, %ebx
|
|
#
|
|
pinsrw $0x04, %esi, %xmm7
|
|
ror $0x10, %esi
|
|
pinsrw $0x05, %esi, %xmm7
|
|
ror $0x10, %esi
|
|
#
|
|
pinsrw $0x06, %edi, %xmm7
|
|
ror $0x10, %edi
|
|
pinsrw $0x07, %edi, %xmm7
|
|
ror $0x10, %edi
|
|
#
|
|
pinsrw $0x00, %esp, %xmm6
|
|
ror $0x10, %esp
|
|
pinsrw $0x01, %esp, %xmm6
|
|
ror $0x10, %esp
|
|
.endm
|
|
|
|
.macro LOAD_REGS
|
|
pshufd $0xe4, %xmm7, %xmm7
|
|
movd %xmm7, %ebp
|
|
pshufd $0xe4, %xmm7, %xmm7
|
|
#
|
|
pshufd $0x39, %xmm7, %xmm7
|
|
movd %xmm7, %ebx
|
|
pshufd $0x93, %xmm7, %xmm7
|
|
#
|
|
pshufd $0x4e, %xmm7, %xmm7
|
|
movd %xmm7, %esi
|
|
pshufd $0x4e, %xmm7, %xmm7
|
|
#
|
|
pshufd $0x93, %xmm7, %xmm7
|
|
movd %xmm7, %edi
|
|
pshufd $0x39, %xmm7, %xmm7
|
|
#
|
|
movd %xmm6, %esp
|
|
.endm
|
|
|
|
.macro LOAD_EAX
|
|
pshufd $0x39, %xmm6, %xmm6
|
|
movd %xmm6, %eax
|
|
pshufd $0x93, %xmm6, %xmm6
|
|
.endm
|
|
|
|
.macro LOAD_EDX
|
|
pshufd $0xe4, %xmm6, %xmm6
|
|
movd %xmm6, %edx
|
|
pshufd $0xe4, %xmm6, %xmm6
|
|
.endm
|
|
|
|
.macro SAVE_EAX
|
|
pinsrw $0x02, %eax, %xmm6
|
|
ror $0x10, %eax
|
|
pinsrw $0x03, %eax, %xmm6
|
|
ror $0x10, %eax
|
|
.endm
|
|
|
|
.macro SAVE_EDX
|
|
pinsrw $0x04, %edx, %xmm6
|
|
ror $0x10, %edx
|
|
pinsrw $0x05, %edx, %xmm6
|
|
ror $0x10, %edx
|
|
.endm
|
|
|
|
.macro LOAD_ESP
|
|
movd %xmm6, %esp
|
|
.endm
|
|
|
|
.macro ENABLE_SSE
|
|
jmp NextAddress
|
|
.align 4
|
|
#
|
|
# 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
|
|
SseError:
|
|
#
|
|
# Processor has to support SSE
|
|
#
|
|
jmp SseError
|
|
NextAddress:
|
|
#
|
|
# 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 SseError
|
|
|
|
#
|
|
# Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
|
|
#
|
|
movl %cr4, %eax
|
|
orl $BIT9, %eax
|
|
movl %eax, %cr4
|
|
|
|
#
|
|
# The processor should support SSE instruction and we can use
|
|
# ldmxcsr instruction
|
|
#
|
|
ldmxcsr ASM_PFX(mMmxControlWord)
|
|
.endm
|
|
|
|
#Save in ECX-SLOT 3 in xmm6.
|
|
.macro SAVE_EAX_MICROCODE_RET_STATUS
|
|
pinsrw $0x6, %eax, %xmm6
|
|
ror $0x10, %eax
|
|
pinsrw $0x7, %eax, %xmm6
|
|
rol $0x10, %eax
|
|
.endm
|
|
|
|
#Restore from ECX-SLOT 3 in xmm6.
|
|
.macro LOAD_EAX_MICROCODE_RET_STATUS
|
|
pshufd $0x93, %xmm6, %xmm6
|
|
movd %xmm6, %eax
|
|
pshufd $0x39, %xmm6, %xmm6
|
|
.endm
|
|
|
|
|
|
|
|
#
|
|
# Following are fixed PCDs
|
|
#
|
|
ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase)
|
|
ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize)
|
|
ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
|
|
|
|
#
|
|
# Following functions will be provided in C
|
|
#
|
|
ASM_GLOBAL ASM_PFX(SecStartup)
|
|
ASM_GLOBAL ASM_PFX(FspApiCallingCheck)
|
|
|
|
#
|
|
# Following functions will be provided in PlatformSecLib
|
|
#
|
|
ASM_GLOBAL ASM_PFX(AsmGetFspBaseAddress)
|
|
ASM_GLOBAL ASM_PFX(AsmGetFspInfoHeader)
|
|
ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)
|
|
ASM_GLOBAL ASM_PFX(Loader2PeiSwitchStack)
|
|
|
|
|
|
#
|
|
# 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)
|
|
|
|
#------------------------------------------------------------------------------
|
|
# SecPlatformInitDefault
|
|
# Inputs:
|
|
# mm7 -> Return address
|
|
# Outputs:
|
|
# eax -> 0 - Successful, Non-zero - Failed.
|
|
# Register Usage:
|
|
# eax is cleared and ebp is used for return address.
|
|
# All others reserved.
|
|
#------------------------------------------------------------------------------
|
|
ASM_GLOBAL ASM_PFX(SecPlatformInitDefault)
|
|
ASM_PFX(SecPlatformInitDefault):
|
|
#
|
|
# Save return address to EBP
|
|
#
|
|
movd %mm7, %ebp
|
|
xorl %eax, %eax
|
|
|
|
SecPlatformInitDefaultExit:
|
|
jmp *%ebp
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# LoadMicrocodeDefault
|
|
#
|
|
# Inputs:
|
|
# esp -> LoadMicrocodeParams 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
|
|
#------------------------------------------------------------------------------
|
|
ASM_GLOBAL ASM_PFX(LoadMicrocodeDefault)
|
|
ASM_PFX(LoadMicrocodeDefault):
|
|
#
|
|
# Save return address to EBP
|
|
#
|
|
movd %mm7, %ebp
|
|
|
|
cmpl $0x00, %esp
|
|
jz ParamError
|
|
movl 4(%esp), %eax #dword ptr [] Parameter pointer
|
|
cmpl $0x00, %eax
|
|
jz ParamError
|
|
movl %eax, %esp
|
|
movl MicrocodeCodeAddr(%esp), %esi
|
|
cmpl $0x00, %esi
|
|
jnz CheckMainHeader
|
|
|
|
ParamError:
|
|
movl $0x080000002, %eax
|
|
jmp LoadMicrocodeExit
|
|
|
|
CheckMainHeader:
|
|
#
|
|
# Get processor signature and platform ID from the installed processor
|
|
# and save into registers for later use
|
|
# ebx = processor signature
|
|
# edx = platform ID
|
|
#
|
|
movl $0x01, %eax
|
|
cpuid
|
|
movl %eax, %ebx
|
|
movl $MSR_IA32_PLATFORM_ID, %ecx
|
|
rdmsr
|
|
movl %edx, %ecx
|
|
shrl $0x12, %ecx # shift (50d-32d=18d=0x12) bits
|
|
andl $0x07, %ecx # platform id at bit[52..50]
|
|
movl $0x01, %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 $0x01, %eax
|
|
cmpl %eax, MicrocodeHdrVersion(%esi)
|
|
jne AdvanceFixedSize
|
|
cmpl %eax, MicrocodeHdrLoader(%esi)
|
|
jne AdvanceFixedSize
|
|
|
|
#
|
|
# Check if signature and plaform ID match
|
|
#
|
|
cmpl MicrocodeHdrProcessor(%esi), %ebx
|
|
jne LoadMicrocodeL0
|
|
testl MicrocodeHdrFlags(%esi), %edx
|
|
jnz LoadCheck #Jif signature and platform ID match
|
|
|
|
LoadMicrocodeL0:
|
|
#
|
|
# Check if extended header exists
|
|
# First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
|
|
#
|
|
xorl %eax, %eax
|
|
cmpl %eax, MicrocodeHdrTotalSize(%esi)
|
|
je NextMicrocode
|
|
cmpl %eax, MicrocodeHdrDataSize(%esi)
|
|
je NextMicrocode
|
|
|
|
#
|
|
# Then verify total size - sizeof header > data size
|
|
#
|
|
movl MicrocodeHdrTotalSize(%esi), %ecx
|
|
subl $MicrocodeHdrLength, %ecx
|
|
cmpl MicrocodeHdrDataSize(%esi), %ecx
|
|
jle NextMicrocode
|
|
|
|
#
|
|
# Set edi -> extended header
|
|
#
|
|
movl %esi, %edi
|
|
addl $MicrocodeHdrLength, %edi
|
|
addl MicrocodeHdrDataSize(%esi), %edi
|
|
|
|
#
|
|
# Get count of extended structures
|
|
#
|
|
movl ExtSigHdrCount(%edi), %ecx
|
|
|
|
#
|
|
# Move pointer to first signature structure
|
|
#
|
|
addl ExtSigHdrLength, %edi
|
|
|
|
CheckExtSig:
|
|
#
|
|
# Check if extended signature and platform ID match
|
|
#
|
|
cmpl %ebx, ExtSigProcessor(%edi)
|
|
jne LoadMicrocodeL1
|
|
test %edx, ExtSigFlags(%edi)
|
|
jnz LoadCheck # Jif signature and platform ID match
|
|
LoadMicrocodeL1:
|
|
#
|
|
# Check if any more extended signatures exist
|
|
#
|
|
addl $ExtSigLength, %edi
|
|
loop CheckExtSig
|
|
|
|
NextMicrocode:
|
|
#
|
|
# Advance just after end of this microcode
|
|
#
|
|
xorl %eax, %eax
|
|
cmpl %eax, MicrocodeHdrTotalSize(%esi)
|
|
je LoadMicrocodeL2
|
|
addl MicrocodeHdrTotalSize(%esi), %esi
|
|
jmp CheckAddress
|
|
LoadMicrocodeL2:
|
|
addl $0x800, %esi #add esi, dword ptr 2048
|
|
jmp CheckAddress
|
|
|
|
AdvanceFixedSize:
|
|
#
|
|
# Advance by 4X dwords
|
|
#
|
|
addl $0x400, %esi #add esi, dword ptr 1024
|
|
|
|
CheckAddress:
|
|
#
|
|
# Is valid Microcode start point ?
|
|
#
|
|
cmpl $0x0ffffffff, MicrocodeHdrVersion(%esi)
|
|
|
|
#
|
|
# Is automatic size detection ?
|
|
#
|
|
movl MicrocodeCodeSize(%esp), %eax
|
|
cmpl $0x0ffffffff, %eax
|
|
jz LoadMicrocodeL3
|
|
#
|
|
# Address >= microcode region address + microcode region size?
|
|
#
|
|
addl MicrocodeCodeAddr(%esp), %eax
|
|
|
|
cmpl %eax, %esi
|
|
jae Done #Jif address is outside of microcode region
|
|
jmp CheckMainHeader
|
|
|
|
LoadMicrocodeL3:
|
|
LoadCheck:
|
|
#
|
|
# 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 $0x01, %eax
|
|
cpuid
|
|
movl $MSR_IA32_BIOS_SIGN_ID, %ecx
|
|
rdmsr # Get current microcode signature
|
|
|
|
#
|
|
# Verify this microcode update is not already loaded
|
|
#
|
|
cmpl %edx, MicrocodeHdrRevision(%esi)
|
|
je Continue
|
|
|
|
LoadMicrocode0:
|
|
#
|
|
# 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
|
|
#
|
|
movl %esi, %eax
|
|
addl $MicrocodeHdrLength, %eax
|
|
xorl %edx, %edx
|
|
movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx
|
|
wrmsr
|
|
movl $0x01, %eax
|
|
cpuid
|
|
|
|
Continue:
|
|
jmp NextMicrocode
|
|
|
|
Done:
|
|
movl $0x01, %eax
|
|
cpuid
|
|
movl $MSR_IA32_BIOS_SIGN_ID, %ecx
|
|
rdmsr # Get current microcode signature
|
|
xorl %eax, %eax
|
|
cmpl $0x00, %edx
|
|
jnz LoadMicrocodeExit
|
|
movl $0x08000000E, %eax
|
|
|
|
LoadMicrocodeExit:
|
|
jmp *%ebp
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# EstablishStackFsp
|
|
#
|
|
#----------------------------------------------------------------------------
|
|
ASM_GLOBAL ASM_PFX(EstablishStackFsp)
|
|
ASM_PFX(EstablishStackFsp):
|
|
#
|
|
# Save parameter pointer in edx
|
|
#
|
|
movl 4(%esp), %edx
|
|
|
|
#
|
|
# Enable FSP STACK
|
|
#
|
|
movl PcdGet32(PcdTemporaryRamBase), %esp
|
|
addl PcdGet32(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
|
|
pushl 4(%edx) # Microcode size
|
|
pushl (%edx) # Microcode base
|
|
|
|
#
|
|
# 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'
|
|
LOAD_EDX
|
|
pushl %edx
|
|
LOAD_EAX
|
|
pushl %eax
|
|
rdtsc
|
|
pushl %edx
|
|
pushl %eax
|
|
|
|
#
|
|
# Terminator for the data on stack
|
|
#
|
|
push $0x00
|
|
|
|
#
|
|
# Set ECX/EDX to the BootLoader temporary memory range
|
|
#
|
|
movl PcdGet32 (PcdTemporaryRamBase), %ecx
|
|
movl %ecx, %edx
|
|
addl PcdGet32 (PcdTemporaryRamSize), %edx
|
|
subl PcdGet32 (PcdFspTemporaryRamSize), %edx
|
|
|
|
xorl %eax, %eax
|
|
|
|
movd %mm7, %esi #RET_ESI
|
|
jmp *%esi
|
|
|
|
#----------------------------------------------------------------------------
|
|
# 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 XMM6
|
|
#
|
|
rdtsc
|
|
SAVE_EAX
|
|
SAVE_EDX
|
|
|
|
#
|
|
# Check Parameter
|
|
#
|
|
movl 4(%esp), %eax
|
|
cmpl $0x00, %eax
|
|
movl $0x80000002, %eax
|
|
jz NemInitExit
|
|
|
|
#
|
|
# Sec Platform Init
|
|
#
|
|
movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit
|
|
movd %esi, %mm7
|
|
.weak ASM_PFX(SecPlatformInit)
|
|
.set ASM_PFX(SecPlatformInit), ASM_PFX(SecPlatformInitDefault)
|
|
jmp ASM_PFX(SecPlatformInit)
|
|
TempRamInitApiL1:
|
|
cmpl $0x00, %eax
|
|
jnz NemInitExit
|
|
|
|
#
|
|
# Load microcode
|
|
#
|
|
LOAD_ESP
|
|
movl $TempRamInitApiL2, %esi #CALL_MMX LoadMicrocode
|
|
movd %esi, %mm7
|
|
.weak ASM_PFX(LoadMicrocode)
|
|
.set ASM_PFX(LoadMicrocode), ASM_PFX(LoadMicrocodeDefault)
|
|
jmp ASM_PFX(LoadMicrocode)
|
|
TempRamInitApiL2:
|
|
SAVE_EAX_MICROCODE_RET_STATUS #Save microcode return status in ECX-SLOT 3 in xmm6.
|
|
#@note If return value eax is not 0, microcode did not load, but continue and attempt to boot from ECX-SLOT 3 in xmm6.
|
|
|
|
#
|
|
# Call Sec CAR Init
|
|
#
|
|
LOAD_ESP
|
|
movl $TempRamInitApiL3, %esi #CALL_MMX SecCarInit
|
|
movd %esi, %mm7
|
|
jmp ASM_PFX(SecCarInit)
|
|
TempRamInitApiL3:
|
|
cmpl $0x00, %eax
|
|
jnz NemInitExit
|
|
|
|
#
|
|
# EstablishStackFsp
|
|
#
|
|
LOAD_ESP
|
|
movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp
|
|
movd %esi, %mm7
|
|
jmp ASM_PFX(EstablishStackFsp)
|
|
TempRamInitApiL4:
|
|
|
|
LOAD_EAX_MICROCODE_RET_STATUS #Restore microcode status if no CAR init error.
|
|
|
|
NemInitExit:
|
|
#
|
|
# Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
|
|
#
|
|
LOAD_REGS
|
|
ret
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
# 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):
|
|
movl $0x01, %eax
|
|
jmp FspApiCommon
|
|
|
|
#----------------------------------------------------------------------------
|
|
# 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):
|
|
movl $0x02, %eax
|
|
jmp FspApiCommon
|
|
|
|
#----------------------------------------------------------------------------
|
|
# FspMemoryInit API
|
|
#
|
|
# This FSP API is called after TempRamInit and initializes the memory.
|
|
#
|
|
#----------------------------------------------------------------------------
|
|
ASM_GLOBAL ASM_PFX(FspMemoryInitApi)
|
|
ASM_PFX(FspMemoryInitApi):
|
|
movl $0x03, %eax
|
|
jmp FspApiCommon
|
|
|
|
#----------------------------------------------------------------------------
|
|
# TempRamExitApi API
|
|
#
|
|
# This API tears down temporary RAM
|
|
#
|
|
#----------------------------------------------------------------------------
|
|
ASM_GLOBAL ASM_PFX(TempRamExitApi)
|
|
ASM_PFX(TempRamExitApi):
|
|
movl $0x04, %eax
|
|
jmp FspApiCommon
|
|
|
|
#----------------------------------------------------------------------------
|
|
# FspSiliconInit API
|
|
#
|
|
# This FSP API initializes the CPU and the chipset including the IO
|
|
# controllers in the chipset to enable normal operation of these devices.
|
|
#
|
|
#----------------------------------------------------------------------------
|
|
ASM_GLOBAL ASM_PFX(FspSiliconInitApi)
|
|
ASM_PFX(FspSiliconInitApi):
|
|
movl $0x05, %eax
|
|
jmp FspApiCommon
|
|
|
|
#----------------------------------------------------------------------------
|
|
# FspApiCommon API
|
|
#
|
|
# This is the FSP API common entry point to resume the FSP execution
|
|
#
|
|
#----------------------------------------------------------------------------
|
|
ASM_GLOBAL ASM_PFX(FspApiCommon)
|
|
ASM_PFX(FspApiCommon):
|
|
#
|
|
# EAX holds the API index
|
|
#
|
|
|
|
#
|
|
# Stack must be ready
|
|
#
|
|
pushl %eax
|
|
addl $0x04, %esp
|
|
cmpl -4(%esp), %eax
|
|
jz FspApiCommonL0
|
|
movl $0x080000003, %eax
|
|
jmp FspApiCommonExit
|
|
|
|
FspApiCommonL0:
|
|
#
|
|
# Verify the calling condition
|
|
#
|
|
pushal
|
|
pushl 36(%esp) #push ApiParam [esp + 4 * 8 + 4]
|
|
pushl %eax #push ApiIdx
|
|
call ASM_PFX(FspApiCallingCheck)
|
|
addl $0x08, %esp
|
|
cmpl $0x00, %eax
|
|
jz FspApiCommonL1
|
|
movl %eax, 0x1C(%esp) # mov dword ptr [esp + 4 * 7], eax
|
|
popal
|
|
ret
|
|
|
|
FspApiCommonL1:
|
|
popal
|
|
cmpl $0x01, %eax # FspInit API
|
|
jz FspApiCommonL2
|
|
cmpl $0x03, %eax # FspMemoryInit API
|
|
jz FspApiCommonL2
|
|
call ASM_PFX(AsmGetFspInfoHeader)
|
|
jmp Loader2PeiSwitchStack
|
|
|
|
FspApiCommonL2:
|
|
#
|
|
# FspInit and FspMemoryInit APIs, setup the initial stack frame
|
|
#
|
|
|
|
#
|
|
# Place holder to store the FspInfoHeader pointer
|
|
#
|
|
pushl %eax
|
|
|
|
#
|
|
# Update the FspInfoHeader pointer
|
|
#
|
|
pushl %eax
|
|
call ASM_PFX(AsmGetFspInfoHeader)
|
|
movl %eax, 4(%esp)
|
|
popl %eax
|
|
|
|
#
|
|
# Create a Task Frame in the stack for the Boot Loader
|
|
#
|
|
pushfl # 2 pushf for 4 byte alignment
|
|
cli
|
|
pushal
|
|
|
|
#
|
|
# Reserve 8 bytes for IDT save/restore
|
|
#
|
|
subl $0x08, %esp
|
|
sidt (%esp)
|
|
|
|
#
|
|
# Setup new FSP stack
|
|
#
|
|
movl %esp, %edi
|
|
movl PcdGet32(PcdTemporaryRamBase), %esp
|
|
addl PcdGet32(PcdTemporaryRamSize), %esp
|
|
subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp
|
|
|
|
#
|
|
# Pass the API Idx to SecStartup
|
|
#
|
|
pushl %eax
|
|
|
|
#
|
|
# Pass the BootLoader stack to SecStartup
|
|
#
|
|
pushl %edi
|
|
|
|
#
|
|
# Pass entry point of the PEI core
|
|
#
|
|
call ASM_PFX(AsmGetFspBaseAddress)
|
|
movl %eax, %edi
|
|
addl PcdGet32(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 implementation with single FV, PcdFspBootFirmwareVolumeBase and
|
|
# PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
|
|
# they are different. The code below can handle both cases.
|
|
#
|
|
call ASM_PFX(AsmGetFspBaseAddress)
|
|
movl %eax, %edi
|
|
call ASM_PFX(GetBootFirmwareVolumeOffset)
|
|
addl %edi, %eax
|
|
pushl %eax
|
|
|
|
#
|
|
# Pass stack base and size into the PEI Core
|
|
#
|
|
movl PcdGet32(PcdTemporaryRamBase), %eax
|
|
addl PcdGet32(PcdTemporaryRamSize), %eax
|
|
subl PcdGet32(PcdFspTemporaryRamSize), %eax
|
|
pushl %eax
|
|
pushl PcdGet32(PcdFspTemporaryRamSize)
|
|
|
|
#
|
|
# Pass Control into the PEI Core
|
|
#
|
|
call ASM_PFX(SecStartup)
|
|
addl $4, %esp
|
|
FspApiCommonExit:
|
|
ret
|
|
|