Fix GCC issue on FspInfoHeaderRelativeOff. Clean up comments for platform ID matching on Microcode and PcdFspBootFirmwareVolumeBase Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: "Yao, Jiewen" <Jiewen.Yao@intel.com> Reviewed-by: "Rangarajan, Ravi P" <ravi.p.rangarajan@intel.com> Reviewed-by: "Mudusuru, Giri P" <giri.p.mudusuru@intel.com> Reviewed-by: "Ma, Maurice" <maurice.ma@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17496 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			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
 | |
| 
 |