123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- ;; @file
- ; Provide FSP API entry points.
- ;
- ; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
- ; SPDX-License-Identifier: BSD-2-Clause-Patent
- ;;
- SECTION .text
- %include "SaveRestoreSseAvxNasm.inc"
- %include "MicrocodeLoadNasm.inc"
- ;
- ; Following are fixed PCDs
- ;
- extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
- extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
- extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
- ;
- ; Following functions will be provided in PlatformSecLib
- ;
- extern ASM_PFX(AsmGetFspBaseAddress)
- extern ASM_PFX(AsmGetFspInfoHeaderNoStack)
- ;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation
- extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation
- extern ASM_PFX(SecCarInit)
- ;
- ; 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)
- ;
- ; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid
- ; build error. This needs to be fixed later on.
- ;
- struc MicrocodeHdr
- .MicrocodeHdrVersion: resd 1
- .MicrocodeHdrRevision: resd 1
- .MicrocodeHdrDate: resd 1
- .MicrocodeHdrProcessor: resd 1
- .MicrocodeHdrChecksum: resd 1
- .MicrocodeHdrLoader: resd 1
- .MicrocodeHdrFlags: resd 1
- .MicrocodeHdrDataSize: resd 1
- .MicrocodeHdrTotalSize: resd 1
- .MicrocodeHdrRsvd: resd 3
- .size:
- endstruc
- struc ExtSigHdr
- .ExtSigHdrCount: resd 1
- .ExtSigHdrChecksum: resd 1
- .ExtSigHdrRsvd: resd 3
- .size:
- endstruc
- struc ExtSig
- .ExtSigProcessor: resd 1
- .ExtSigFlags: resd 1
- .ExtSigChecksum: resd 1
- .size:
- endstruc
- struc LoadMicrocodeParamsFsp24
- ; FSP_UPD_HEADER {
- .FspUpdHeaderSignature: resd 2
- .FspUpdHeaderRevision: resb 1
- .FspUpdHeaderReserved: resb 23
- ; }
- ; FSPT_ARCH2_UPD {
- .FsptArchRevision: resb 1
- .FsptArchReserved: resb 3
- .FsptArchLength: resd 1
- .FspDebugHandler resq 1
- .FsptArchUpd: resd 4
- ; }
- ; FSPT_CORE_UPD {
- .MicrocodeCodeAddr: resq 1
- .MicrocodeCodeSize: resq 1
- .CodeRegionBase: resq 1
- .CodeRegionSize: resq 1
- ; }
- .size:
- endstruc
- %macro CALL_RDI 1
- mov rdi, %%ReturnAddress
- jmp %1
- %%ReturnAddress:
- %endmacro
- ;
- ; @todo: The strong/weak implementation does not work.
- ; This needs to be reviewed later.
- ;
- ;------------------------------------------------------------------------------
- ;
- ;;global ASM_PFX(SecPlatformInitDefault)
- ;ASM_PFX(SecPlatformInitDefault):
- ; ; Inputs:
- ; ; ymm7 -> Return address
- ; ; Outputs:
- ; ; rax -> 0 - Successful, Non-zero - Failed.
- ; ; Register Usage:
- ; ; rax is cleared and rbp is used for return address.
- ; ; All others reserved.
- ;
- ; ; Save return address to RBP
- ; LOAD_RBP
- ;
- ; xor rax, rax
- ;Exit1:
- ; jmp rbp
- ;------------------------------------------------------------------------------
- global ASM_PFX(LoadMicrocodeDefault)
- ASM_PFX(LoadMicrocodeDefault):
- ; Inputs:
- ; rcx -> LoadMicrocodeParams pointer
- ; Register Usage:
- ; All are 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 RBP
- ;
- LOAD_RBP
- test rsp, rsp
- jz ParamError
- test rcx, rcx
- jz ParamError
- mov rsp, rcx
- ;
- ; If microcode already loaded before this function, exit this function with SUCCESS.
- ;
- 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
- xor rax, rax
- test edx, edx
- jnz Exit2
- ; skip loading Microcode if the MicrocodeCodeSize is zero
- ; and report error if size is less than 2k
- ; first check UPD header revision
- cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
- jb ParamError
- cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
- jne ParamError
- ; UPD structure is compliant with FSP spec 2.4
- mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
- test rax, rax
- jz Exit2
- cmp rax, 0800h
- jl ParamError
- mov rsi, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
- test rsi, rsi
- jnz CheckMainHeader
- ParamError:
- mov rax, 08000000000000002h
- jmp Exit2
- CheckMainHeader:
- ; 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 parameters
- ; 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 1
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
- jne AdvanceFixedSize
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
- jne AdvanceFixedSize
- ; Check if signature and plaform ID match
- cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
- jne LoadMicrocodeDefault1
- test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
- jnz LoadMicrocode ; Jif signature and platform ID match
- LoadMicrocodeDefault1:
- ; Check if extended header exists
- ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
- xor rax, rax
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
- je NextMicrocode
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
- je NextMicrocode
- ; Then verify total size - sizeof header > data size
- mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
- sub ecx, MicrocodeHdr.size
- cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
- jng NextMicrocode ; Jif extended header does not exist
- ; Set edi -> extended header
- mov edi, esi
- add edi, MicrocodeHdr.size
- add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
- ; Get count of extended structures
- mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
- ; Move pointer to first signature structure
- add edi, ExtSigHdr.size
- CheckExtSig:
- ; Check if extended signature and platform ID match
- cmp dword [edi + ExtSig.ExtSigProcessor], ebx
- jne LoadMicrocodeDefault2
- test dword [edi + ExtSig.ExtSigFlags], edx
- jnz LoadMicrocode ; Jif signature and platform ID match
- LoadMicrocodeDefault2:
- ; Check if any more extended signatures exist
- add edi, ExtSig.size
- loop CheckExtSig
- NextMicrocode:
- ; Advance just after end of this microcode
- xor rax, rax
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
- je LoadMicrocodeDefault3
- add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
- jmp CheckAddress
- LoadMicrocodeDefault3:
- add esi, dword 2048
- jmp CheckAddress
- AdvanceFixedSize:
- ; Advance by 4X dwords
- add esi, dword 1024
- CheckAddress:
- ; Check UPD header revision
- cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
- jb ParamError
- cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
- jne ParamError
- ; UPD structure is compliant with FSP spec 2.4
- ; Is automatic size detection ?
- mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
- mov rcx, 0ffffffffffffffffh
- cmp rax, rcx
- jz LoadMicrocodeDefault4
- ; Address >= microcode region address + microcode region size?
- add rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
- cmp rsi, rax
- jae Done ;Jif address is outside of microcode region
- jmp CheckMainHeader
- LoadMicrocodeDefault4:
- ; Is valid Microcode start point ?
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
- jz Done
- jmp CheckMainHeader
- LoadMicrocode:
- ; 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, MicrocodeHdr.size
- xor edx, edx
- mov ecx, MSR_IA32_BIOS_UPDT_TRIG
- wrmsr
- mov eax, 1
- cpuid
- Done:
- 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
- xor eax, eax
- test edx, edx
- jnz Exit2
- mov rax, 0800000000000000Eh
- Exit2:
- jmp rbp
- global ASM_PFX(EstablishStackFsp)
- ASM_PFX(EstablishStackFsp):
- ;
- ; Save parameter pointer in rdx
- ;
- mov rdx, rcx
- ;
- ; Enable FSP STACK
- ;
- mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
- mov esp, DWORD[rax]
- mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
- add esp, DWORD[rax]
- sub esp, 4
- mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region
- sub esp, 4
- mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'
- ; check UPD structure revision (rdx + 8)
- cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
- jb ParamError1
- cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
- je Fsp24UpdHeader
- ParamError1:
- mov rax, 08000000000000002h
- jmp EstablishStackFspExit
- Fsp24UpdHeader:
- ; UPD structure is compliant with FSP spec 2.4
- xor rax, rax
- mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h
- sub rsp, 8
- mov qword[rsp], rax
- mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h
- sub rsp, 8
- mov qword[rsp], rax
- mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h
- sub rsp, 8
- mov qword[rsp], rax
- mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h
- sub rsp, 8
- mov qword[rsp], rax
- ContinueAfterUpdPush:
- ;
- ; Save API entry/exit timestamp into stack
- ;
- sub esp, 4
- mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region
- sub esp, 4
- mov dword[esp], 30524550h ; Signature of the data region 'PER0'
- rdtsc
- sub esp, 4
- mov dword[esp], edx
- sub esp, 4
- mov dword[esp], eax
- LOAD_TS rax
- push rax
- ;
- ; Terminator for the data on stack
- ;
- push 0
- ;
- ; Set ECX/EDX to the BootLoader temporary memory range
- ;
- mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
- mov edx, [ecx]
- mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
- add edx, [ecx]
- mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
- sub edx, [ecx]
- mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
- mov ecx, [ecx]
- cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
- jb EstablishStackFspSuccess
- mov rax, 08000000000000003h ; EFI_UNSUPPORTED
- jmp EstablishStackFspExit
- EstablishStackFspSuccess:
- xor rax, rax
- EstablishStackFspExit:
- RET_YMM
- ;----------------------------------------------------------------------------
- ; 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.
- ;
- ;----------------------------------------------------------------------------
- global ASM_PFX(TempRamInitApi)
- ASM_PFX(TempRamInitApi):
- ;
- ; Ensure both SSE and AVX are enabled
- ;
- ENABLE_SSE
- ENABLE_AVX
- ;
- ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6
- ;
- SAVE_REGS
- ;
- ; Save BFV address in YMM9
- ;
- SAVE_BFV rbp
- ;
- ; Save Input Parameter in YMM10
- ;
- cmp rcx, 0
- jnz ParamValid
- ;
- ; Fall back to default UPD
- ;
- CALL_RDI ASM_PFX(AsmGetFspInfoHeaderNoStack)
- xor rcx, rcx
- mov ecx, DWORD [rax + 01Ch] ; Read FsptImageBaseAddress
- add ecx, DWORD [rax + 024h] ; Get Cfg Region base address = FsptImageBaseAddress + CfgRegionOffset
- ParamValid:
- SAVE_RCX
- ;
- ; Save timestamp into YMM6
- ;
- rdtsc
- shl rdx, 32
- or rax, rdx
- SAVE_TS rax
- ;
- ; Sec Platform Init
- ;
- CALL_YMM ASM_PFX(SecPlatformInit)
- test rax, rax
- jnz TempRamInitExit
- ; Load microcode
- LOAD_RCX
- CALL_YMM ASM_PFX(LoadMicrocodeDefault)
- SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).
- ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.
- ; Call Sec CAR Init
- LOAD_RCX
- CALL_YMM ASM_PFX(SecCarInit)
- test rax, rax
- jnz TempRamInitExit
- LOAD_RCX
- CALL_YMM ASM_PFX(EstablishStackFsp)
- test rax, rax
- jnz TempRamInitExit
- LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).
- TempRamInitExit:
- mov bl, al ; save al data in bl
- mov al, 07Fh ; API exit postcode 7f
- out 080h, al
- mov al, bl ; restore al data from bl
- ;
- ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6
- ;
- LOAD_REGS
- LOAD_BFV rbp
- ret
- ;----------------------------------------------------------------------------
- ; Module Entrypoint API
- ;----------------------------------------------------------------------------
- global ASM_PFX(_ModuleEntryPoint)
- ASM_PFX(_ModuleEntryPoint):
- jmp $
|