123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- ;; @file
- ; Provide FSP API entry points.
- ;
- ; Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
- ; SPDX-License-Identifier: BSD-2-Clause-Patent
- ;;
- .586p
- .model flat,C
- .code
- .xmm
- INCLUDE SaveRestoreSse.inc
- INCLUDE MicrocodeLoad.inc
- ;
- ; Following are fixed PCDs
- ;
- EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
- EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
- EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
- EXTERN PcdGet32(PcdFspAreaSize):DWORD
- ;
- ; Following functions will be provided in C
- ;
- EXTERN SecStartup:PROC
- EXTERN FspApiCallingCheck:PROC
- ;
- ; Following functions will be provided in PlatformSecLib
- ;
- EXTERN AsmGetFspBaseAddress:PROC
- EXTERN AsmGetFspInfoHeader:PROC
- EXTERN GetBootFirmwareVolumeOffset:PROC
- EXTERN Loader2PeiSwitchStack:PROC
- EXTERN LoadMicrocode(LoadMicrocodeDefault):PROC
- EXTERN SecPlatformInit(SecPlatformInitDefault):PROC
- EXTERN SecCarInit: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)
- ;
- ; Define SSE macros
- ;
- LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister
- mov esi, ReturnAddress
- movd MmxRegister, esi ; save ReturnAddress into MMX
- ENDM
- CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
- local ReturnAddress
- mov esi, offset ReturnAddress
- movd MmxRegister, esi ; save ReturnAddress into MMX
- jmp RoutineLabel
- ReturnAddress:
- ENDM
- RET_ESI_EXT MACRO MmxRegister
- movd esi, MmxRegister ; move ReturnAddress from MMX to ESI
- jmp esi
- ENDM
- CALL_MMX MACRO RoutineLabel
- CALL_MMX_EXT RoutineLabel, mm7
- ENDM
- RET_ESI MACRO
- RET_ESI_EXT mm7
- ENDM
- ;------------------------------------------------------------------------------
- SecPlatformInitDefault PROC NEAR PUBLIC
- ; 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.
-
- ; Save return address to EBP
- movd ebp, mm7
- xor eax, eax
- exit:
- jmp ebp
- SecPlatformInitDefault ENDP
- ;------------------------------------------------------------------------------
- LoadMicrocodeDefault PROC NEAR PUBLIC
- ; 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
- ;
- ;
- ; Save return address to EBP
- movd ebp, mm7
- cmp esp, 0
- jz paramerror
- mov eax, dword ptr [esp + 4] ; Parameter pointer
- cmp eax, 0
- jz paramerror
- mov esp, eax
- mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
- cmp esi, 0
- jnz check_main_header
- paramerror:
- mov eax, 080000002h
- jmp exit
- mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
- 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 ; shift (50d-32d=18d=0x12) bits
- and ecx, 7h ; platform id at bit[52..50]
- mov edx, 1
- shl edx, cl
- ; Current register usage
- ; esp -> stack with 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].MicrocodeHdr.MicrocodeHdrVersion, eax
- jne advance_fixed_size
- cmp [esi].MicrocodeHdr.MicrocodeHdrLoader, eax
- jne advance_fixed_size
- ; Check if signature and plaform ID match
- cmp ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor
- jne @f
- test edx, [esi].MicrocodeHdr.MicrocodeHdrFlags
- jnz load_check ; Jif signature and platform ID match
- @@:
- ; Check if extended header exists
- ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
- xor eax, eax
- cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
- je next_microcode
- cmp [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax
- je next_microcode
- ; Then verify total size - sizeof header > data size
- mov ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
- sub ecx, sizeof MicrocodeHdr
- cmp ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize
- jng next_microcode ; Jif extended header does not exist
- ; Set edi -> extended header
- mov edi, esi
- add edi, sizeof MicrocodeHdr
- add edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize
- ; Get count of extended structures
- mov ecx, [edi].ExtSigHdr.ExtSigHdrCount
- ; Move pointer to first signature structure
- add edi, sizeof ExtSigHdr
- check_ext_sig:
- ; Check if extended signature and platform ID match
- cmp [edi].ExtSig.ExtSigProcessor, ebx
- jne @f
- test [edi].ExtSig.ExtSigFlags, edx
- jnz load_check ; Jif signature and platform ID match
- @@:
- ; Check if any more extended signatures exist
- add edi, sizeof ExtSig
- loop check_ext_sig
- next_microcode:
- ; Advance just after end of this microcode
- xor eax, eax
- cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
- je @f
- add esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
- 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].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh
- jz done
- ; Is automatic size detection ?
- mov eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize
- cmp eax, 0ffffffffh
- jz @f
- ; Address >= microcode region address + microcode region size?
- add eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
- cmp esi, eax
- jae done ;Jif address is outside of microcode 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].MicrocodeHdr.MicrocodeHdrRevision, 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 MicrocodeHdr
- 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
- LoadMicrocodeDefault ENDP
- EstablishStackFsp PROC NEAR PRIVATE
- ;
- ; 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 + 12] ; Code size
- push dword ptr [edx + 8] ; Code base
- push dword ptr [edx + 4] ; Microcode size
- push dword ptr [edx] ; Microcode 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'
- LOAD_EDX
- push edx
- LOAD_EAX
- push eax
- rdtsc
- 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
- RET_ESI
- EstablishStackFsp 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 XMM6
- ;
- rdtsc
- SAVE_EAX
- SAVE_EDX
- ;
- ; Check Parameter
- ;
- mov eax, dword ptr [esp + 4]
- cmp eax, 0
- mov eax, 80000002h
- jz TempRamInitExit
- ;
- ; Sec Platform Init
- ;
- CALL_MMX SecPlatformInit
- cmp eax, 0
- jnz TempRamInitExit
- ; Load microcode
- LOAD_ESP
- CALL_MMX LoadMicrocode
- SXMMN xmm6, 3, eax ;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.
- ; Call Sec CAR Init
- LOAD_ESP
- CALL_MMX SecCarInit
- cmp eax, 0
- jnz TempRamInitExit
- LOAD_ESP
- CALL_MMX EstablishStackFsp
- LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
- TempRamInitExit:
- ;
- ; 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
- mov eax, 1
- jmp FspApiCommon
- FspInitApi ENDP
- ;----------------------------------------------------------------------------
- ; NotifyPhase API
- ;
- ; This FSP API will notify the FSP about the different phases in the boot
- ; process
- ;
- ;----------------------------------------------------------------------------
- NotifyPhaseApi PROC C PUBLIC
- mov eax, 2
- jmp FspApiCommon
- NotifyPhaseApi ENDP
- ;----------------------------------------------------------------------------
- ; FspMemoryInit API
- ;
- ; This FSP API is called after TempRamInit and initializes the memory.
- ;
- ;----------------------------------------------------------------------------
- FspMemoryInitApi PROC NEAR PUBLIC
- mov eax, 3
- jmp FspApiCommon
- FspMemoryInitApi ENDP
- ;----------------------------------------------------------------------------
- ; TempRamExitApi API
- ;
- ; This API tears down temporary RAM
- ;
- ;----------------------------------------------------------------------------
- TempRamExitApi PROC C PUBLIC
- mov eax, 4
- jmp FspApiCommon
- TempRamExitApi ENDP
- ;----------------------------------------------------------------------------
- ; 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.
- ;
- ;----------------------------------------------------------------------------
- FspSiliconInitApi PROC C PUBLIC
- mov eax, 5
- jmp FspApiCommon
- FspSiliconInitApi ENDP
- ;----------------------------------------------------------------------------
- ; FspApiCommon API
- ;
- ; This is the FSP API common entry point to resume the FSP execution
- ;
- ;----------------------------------------------------------------------------
- FspApiCommon PROC C PUBLIC
- ;
- ; EAX holds the API index
- ;
- ;
- ; Stack must be ready
- ;
- push eax
- add esp, 4
- cmp eax, dword ptr [esp - 4]
- jz @F
- mov eax, 080000003h
- jmp exit
- @@:
- ;
- ; Verify the calling condition
- ;
- pushad
- push [esp + 4 * 8 + 4] ; push ApiParam
- push eax ; push ApiIdx
- call FspApiCallingCheck
- add esp, 8
- cmp eax, 0
- jz @F
- mov dword ptr [esp + 4 * 7], eax
- popad
- ret
- @@:
- popad
- cmp eax, 1 ; FspInit API
- jz @F
- cmp eax, 3 ; FspMemoryInit API
- jz @F
- call AsmGetFspInfoHeader
- jmp Loader2PeiSwitchStack
- @@:
- ;
- ; FspInit and FspMemoryInit APIs, setup the initial stack frame
- ;
-
- ;
- ; Place holder to store the FspInfoHeader pointer
- ;
- push eax
- ;
- ; Update the FspInfoHeader pointer
- ;
- push eax
- call AsmGetFspInfoHeader
- mov [esp + 4], eax
- pop eax
- ;
- ; 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 edi, esp
- mov esp, PcdGet32(PcdTemporaryRamBase)
- add esp, PcdGet32(PcdTemporaryRamSize)
- sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
- ;
- ; Pass the API Idx to SecStartup
- ;
- push eax
-
- ;
- ; Pass the BootLoader stack to SecStartup
- ;
- push edi
- ;
- ; Pass entry point of the PEI core
- ;
- call AsmGetFspBaseAddress
- mov edi, eax
- add edi, PcdGet32 (PcdFspAreaSize)
- sub edi, 20h
- add eax, DWORD PTR ds:[edi]
- push 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 AsmGetFspBaseAddress
- 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
- add esp, 4
- exit:
- ret
- FspApiCommon ENDP
- END
|