X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=IntelFspPkg%2FFspSecCore%2FIa32%2FFspApiEntry.s;h=8f4093ca1940a7adad50ba5b895950ec0ea51fb5;hp=433ef921c4f1b679415b9d0dea90bd3bd7765329;hb=12a92f51f0efaa0c4f7abdaf869984ae1c65f430;hpb=c8ec22a266cdd134ac99c3021003710130613a40 diff --git a/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s index 433ef921c4..8f4093ca19 100644 --- a/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s +++ b/IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s @@ -1,6 +1,6 @@ #------------------------------------------------------------------------------ # -# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.
# 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 @@ -15,310 +15,517 @@ # #------------------------------------------------------------------------------ -#.INCLUDE "UcodeLoad.inc" -# -# Following are fixed PCDs -# +.equ MSR_IA32_PLATFORM_ID, 0x00000017 +.equ MSR_IA32_BIOS_UPDT_TRIG, 0x00000079 +.equ MSR_IA32_BIOS_SIGN_ID, 0x0000008b -.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) +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 # -# Following functions will be provided in C + pinsrw $0x02, %ebx, %xmm7 + ror $0x10, %ebx + pinsrw $0x03, %ebx, %xmm7 + ror $0x10, %ebx # -#EXTERNDEF SecStartup:PROC -#EXTERNDEF FspApiCallingCheck:PROC - + pinsrw $0x04, %esi, %xmm7 + ror $0x10, %esi + pinsrw $0x05, %esi, %xmm7 + ror $0x10, %esi # -# Following functions will be provided in PlatformSecLib + pinsrw $0x06, %edi, %xmm7 + ror $0x10, %edi + pinsrw $0x07, %edi, %xmm7 + ror $0x10, %edi # -#EXTERNDEF GetFspBaseAddress:PROC -#EXTERNDEF GetBootFirmwareVolumeOffset:PROC -#EXTERNDEF PlatformTempRamInit:PROC -#EXTERNDEF Pei2LoaderSwitchStack:PROC -#EXTERN FspSelfCheck(FspSelfCheckDflt):PROC -#EXTERN PlatformBasicInit(PlatformBasicInitDflt):PROC + 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 # -# Define the data length that we saved on the stack top + pshufd $0x39, %xmm7, %xmm7 + movd %xmm7, %ebx + pshufd $0x93, %xmm7, %xmm7 # -.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) - + pshufd $0x4e, %xmm7, %xmm7 + movd %xmm7, %esi + pshufd $0x4e, %xmm7, %xmm7 # -# Define SSE macros + pshufd $0x93, %xmm7, %xmm7 + movd %xmm7, %edi + pshufd $0x39, %xmm7, %xmm7 # -.macro ENABLE_SSE - movl %cr4, %eax - orl $0x00000600,%eax # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10) - movl %eax,%cr4 + movd %xmm6, %esp .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 +.macro LOAD_EAX + pshufd $0x39, %xmm6, %xmm6 + movd %xmm6, %eax + pshufd $0x93, %xmm6, %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 +.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 -#------------------------------------------------------------------------------ -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. +.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 return address to EBP - movl %eax, %ebp - xorl %eax, %eax -exit: - jmp *%ebp -#FspSelfCheckDflt ENDP +#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 -#------------------------------------------------------------------------------ -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. +#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 - movl %eax, %ebp + # + movd %mm7, %ebp xorl %eax, %eax -exit2: + +SecPlatformInitDefaultExit: 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 - # +#------------------------------------------------------------------------------ +# 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 - 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 + # + movd %mm7, %ebp -paramerror: - movl $0x080000002, %eax - jmp exit4 + 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 - movl (%esp), %esi #.LOAD_UCODE_PARAMS.ucode_code_addr +ParamError: + movl $0x080000002, %eax + jmp LoadMicrocodeExit -check_main_header: +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 $1, %eax + # + movl $0x01, %eax cpuid movl %eax, %ebx - movl MSR_IA32_PLATFORM_ID, %ecx + movl $MSR_IA32_PLATFORM_ID, %ecx rdmsr - movl %edx, %ecx - #-------------------------------------------------------------------------------------------------------------------- - shrl $18, %ecx #($50-$32) - andl $0x7, %ecx - movl $1, %edx - shll %cl,%edx + movl %edx, %ecx + shrl $0x12, %ecx #($50-$32) + andl $0x07, %ecx + 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 $1, %eax - cmpl %eax, (%esi) #.ucode_hdr.version - jne advance_fixed_size - cmpl %eax, 0x18(%esi) #.ucode_hdr.loader - jne advance_fixed_size + # + movl $0x01, %eax + cmpl %eax, MicrocodeHdrVersion(%esi) + jne AdvanceFixedSize + cmpl %eax, MicrocodeHdrLoader(%esi) + jne AdvanceFixedSize + # # 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 + # + cmpl MicrocodeHdrProcessor(%esi), %ebx + jne LoadMicrocodeL0 + testl MicrocodeHdrFlags(%esi), %edx + jnz LoadCheck #Jif signature and platform ID match -L0: +LoadMicrocodeL0: + # # 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 + # 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 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 + # + movl MicrocodeHdrTotalSize(%esi), %ecx + subl $MicrocodeHdrLength, %ecx + cmpl MicrocodeHdrDataSize(%esi), %ecx + jle NextMicrocode + # # Set edi -> extended header - movl %esi , %edi - addl $0x30 , %edi #sizeof ucode_hdr = 48 - addl 0x20(%esi), %edi #%esi.ucode_hdr.data_size + # + movl %esi, %edi + addl $MicrocodeHdrLength, %edi + addl MicrocodeHdrDataSize(%esi), %edi + # # Get count of extended structures - movl (%edi), %ecx #(%edi).ext_sig_hdr.count + # + movl ExtSigHdrCount(%edi), %ecx + # # Move pointer to first signature structure - addl $0x20, %edi # sizeof ext_sig_hdr = 20 + # + addl ExtSigHdrLength, %edi -check_ext_sig: +CheckExtSig: + # # 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: + # + 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 $0xc, %edi #sizeof ext_sig = 12 - loop check_ext_sig + # + addl $ExtSigLength, %edi + loop CheckExtSig -next_microcode: +NextMicrocode: + # # 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: + 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 + # + addl $0x400, %esi #add esi, dword ptr 1024 -check_address: +CheckAddress: + # # Is valid Microcode start point ? - cmp $0x0ffffffff , %esi - jz done + # + cmpl $0x0ffffffff, MicrocodeHdrVersion(%esi) + # + # Is automatic size detection ? + # + movl MicrocodeCodeSize(%esp), %eax + cmpl $0x0ffffffff, %eax + jz LoadMicrocodeL3 + # # 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 + # + addl MicrocodeCodeAddr(%esp), %eax + cmpl %eax, %esi - jae done #Jif address is outside of ucode region - jmp check_main_header + jae Done #Jif address is outside of microcode region + jmp CheckMainHeader -load_check: +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 $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 + movl $0x01, %eax cpuid - movl MSR_IA32_BIOS_SIGN_ID, %ecx - rdmsr # Get current microcode signature + 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 + # + cmpl %edx, MicrocodeHdrRevision(%esi) + je Continue -load_microcode: +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 - mov %esi, %eax - add $0x30, %eax #sizeof ucode_hdr = 48 - xorl %edx, %edx - mov MSR_IA32_BIOS_UPDT_TRIG,%ecx + # + movl %esi, %eax + addl $MicrocodeHdrLength, %eax + xorl %edx, %edx + movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx wrmsr - mov $1, %eax + movl $0x01, %eax cpuid -continue: - jmp next_microcode +Continue: + jmp NextMicrocode -done: - mov $1, %eax +Done: + movl $0x01, %eax cpuid - mov MSR_IA32_BIOS_SIGN_ID, %ecx - rdmsr # Get current microcode signature + movl $MSR_IA32_BIOS_SIGN_ID, %ecx + rdmsr # Get current microcode signature xorl %eax, %eax - cmp $0 , %edx - jnz exit4 - mov $0x08000000E, %eax + cmpl $0x00, %edx + jnz LoadMicrocodeExit + movl $0x08000000E, %eax -exit4: +LoadMicrocodeExit: jmp *%ebp -#LoadUcode ENDP + +#---------------------------------------------------------------------------- +# 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 @@ -341,105 +548,66 @@ ASM_PFX(TempRamInitApi): SAVE_REGS # - # Save timestamp into XMM4 & XMM5 + # Save timestamp into XMM6 # rdtsc - movd %edx, %xmm4 - movd %eax, %xmm5 + SAVE_EAX + SAVE_EDX # - # CPUID/DeviceID check + # Check Parameter # - movl L11, %eax - jmp ASM_PFX(FspSelfCheck) # Note: ESP can not be changed. -L11: - cmpl $0, %eax - jnz NemInitExit + movl 4(%esp), %eax + cmpl $0x00, %eax + movl $0x80000002, %eax + jz NemInitExit # - # Platform Basic Init. + # Sec Platform Init # - movl L1, %eax - jmp ASM_PFX(PlatformBasicInitDflt) -L1: - cmp $0, %eax - jnz NemInitExit + 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 # - 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 + 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. # - # 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 + # Call Sec CAR Init # - pushl $0 + LOAD_ESP + movl $TempRamInitApiL3, %esi #CALL_MMX SecCarInit + movd %esi, %mm7 + jmp ASM_PFX(SecCarInit) +TempRamInitApiL3: + cmpl $0x00, %eax + jnz NemInitExit # - # Set ECX/EDX to the bootloader temporary memory range + # EstablishStackFsp # - movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %ecx - movl %ecx, %edx - addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %edx - subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %edx + LOAD_ESP + movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp + movd %esi, %mm7 + jmp ASM_PFX(EstablishStackFsp) +TempRamInitApiL4: - xorl %eax, %eax + LOAD_EAX_MICROCODE_RET_STATUS #Restore microcode status if no CAR init error. NemInitExit: # @@ -447,7 +615,7 @@ NemInitExit: # LOAD_REGS ret -#TempRamInitApi ENDP + #---------------------------------------------------------------------------- # FspInit API @@ -459,77 +627,159 @@ NemInitExit: #---------------------------------------------------------------------------- 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): # - # Stack must be ready + # EAX holds the API index + # + # - pushl $0x087654321 - pop %eax - cmpl $0x087654321, %eax - jz L5 + # Stack must be ready + # + pushl %eax + addl $0x04, %esp + cmpl -4(%esp), %eax + jz FspApiCommonL0 movl $0x080000003, %eax - jmp exit3 + jmp FspApiCommonExit -L5: +FspApiCommonL0: # - # Additional check + # Verify the calling condition # - pusha - pushl $1 + pushal + pushl 36(%esp) #push ApiParam [esp + 4 * 8 + 4] + pushl %eax #push ApiIdx call ASM_PFX(FspApiCallingCheck) - addl $4, %esp - movl %eax, 28(%esp) - popa - cmpl $0 , %eax - jz L6 - jmp exit3 + 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 -L6: +FspApiCommonL2: # - # Save the Platform Data Pointer in EDI + # FspInit and FspMemoryInit APIs, setup the initial stack frame + # + # - movl 4(%esp), %edi + # Place holder to store the FspInfoHeader pointer + # + pushl %eax # - # Store the address in FSP which will return control to the BL + # Update the FspInfoHeader pointer # - pushl $exit3 + pushl %eax + call ASM_PFX(AsmGetFspInfoHeader) + movl %eax, 4(%esp) + popl %eax # # Create a Task Frame in the stack for the Boot Loader # - pushfl - pushfl # 2 pushf for 4 byte alignment + pushfl # 2 pushf for 4 byte alignment cli pushal + # # Reserve 8 bytes for IDT save/restore - pushl $0 - pushl $0 - sidt (%esp) + # + subl $0x08, %esp + 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 + movl %esp, %edi + movl PcdGet32(PcdTemporaryRamBase), %esp + addl PcdGet32(PcdTemporaryRamSize), %esp + subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp # - # Save the bootloader's stack pointer + # Pass the API Idx to SecStartup # - pushl %eax + pushl %eax + + # + # Pass the BootLoader stack to SecStartup + # + pushl %edi # # 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 + 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 @@ -538,74 +788,26 @@ L6: # 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 + 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 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) + 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) - -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: + addl $4, %esp +FspApiCommonExit: ret -L8: - jmp ASM_PFX(Pei2LoaderSwitchStack) - -#NotifyPhaseApi ENDP - - -#END