REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3017 Platform microcode FV may have padding between each version of microcode binary, and current FSP-T/LoadMicrocodeDefault() cannot handle this case and return not_found unexpectedly. Cc: Maurice Ma <maurice.ma@intel.com> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Chasel Chiu <chasel.chiu@intel.com> Signed-off-by: Cosmo Lai <cosmo.lai@intel.com> Reviewed-by: Chasel Chiu <chasel.chiu@intel.com> Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
		
			
				
	
	
		
			540 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			540 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
| ;; @file
 | |
| ;  Provide FSP API entry points.
 | |
| ;
 | |
| ; Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
 | |
| ; SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| ;;
 | |
| 
 | |
|     SECTION .text
 | |
| 
 | |
| %include    "SaveRestoreSseNasm.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(AsmGetFspInfoHeader)
 | |
| ;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 LoadMicrocodeParams
 | |
|     ; FSP_UPD_HEADER {
 | |
|     .FspUpdHeader:            resd    8
 | |
|     ; }
 | |
|     ; FSPT_CORE_UPD {
 | |
|     .MicrocodeCodeAddr:       resd    1
 | |
|     .MicrocodeCodeSize:       resd    1
 | |
|     .CodeRegionBase:          resd    1
 | |
|     .CodeRegionSize:          resd    1
 | |
|     ; }
 | |
|     .size:
 | |
| endstruc
 | |
| 
 | |
| struc LoadMicrocodeParamsFsp22
 | |
|     ; FSP_UPD_HEADER {
 | |
|     .FspUpdHeaderSignature:   resd    2
 | |
|     .FspUpdHeaderRevision:    resb    1
 | |
|     .FspUpdHeaderReserved:    resb   23
 | |
|     ; }
 | |
|     ; FSPT_ARCH_UPD{
 | |
|     .FsptArchUpd:             resd    8
 | |
|     ; }
 | |
|     ; FSPT_CORE_UPD {
 | |
|     .MicrocodeCodeAddr:       resd    1
 | |
|     .MicrocodeCodeSize:       resd    1
 | |
|     .CodeRegionBase:          resd    1
 | |
|     .CodeRegionSize:          resd    1
 | |
|     ; }
 | |
|     .size:
 | |
| endstruc
 | |
| 
 | |
| ;
 | |
| ; Define SSE macros
 | |
| ;
 | |
| ;
 | |
| ;args 1: ReturnAddress  2:MmxRegister
 | |
| ;
 | |
| %macro LOAD_MMX_EXT 2
 | |
|   mov     esi, %1
 | |
|   movd    %2, esi              ; save ReturnAddress into MMX
 | |
| %endmacro
 | |
| 
 | |
| ;
 | |
| ;args 1: RoutineLabel  2:MmxRegister
 | |
| ;
 | |
| %macro CALL_MMX_EXT  2
 | |
|   mov     esi, %%ReturnAddress
 | |
|   movd    %2, esi              ; save ReturnAddress into MMX
 | |
|   jmp     %1
 | |
| %%ReturnAddress:
 | |
| %endmacro
 | |
| 
 | |
| ;
 | |
| ;arg 1:MmxRegister
 | |
| ;
 | |
| %macro RET_ESI_EXT   1
 | |
|   movd    esi, %1              ; move ReturnAddress from MMX to ESI
 | |
|   jmp     esi
 | |
| %endmacro
 | |
| 
 | |
| ;
 | |
| ;arg 1:RoutineLabel
 | |
| ;
 | |
| %macro CALL_MMX   1
 | |
|          CALL_MMX_EXT  %1, mm7
 | |
| %endmacro
 | |
| 
 | |
| %macro RET_ESI 0
 | |
|          RET_ESI_EXT   mm7
 | |
| %endmacro
 | |
| 
 | |
| ;
 | |
| ; @todo: The strong/weak implementation does not work.
 | |
| ;        This needs to be reviewed later.
 | |
| ;
 | |
| ;------------------------------------------------------------------------------
 | |
| ;
 | |
| ;;global ASM_PFX(SecPlatformInitDefault)
 | |
| ;ASM_PFX(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.
 | |
| ;
 | |
| ;   ; Save return address to EBP
 | |
| ;   movd  ebp, mm7
 | |
| ;
 | |
| ;   xor   eax, eax
 | |
| ;Exit1:
 | |
| ;   jmp   ebp
 | |
| 
 | |
| ;------------------------------------------------------------------------------
 | |
| global ASM_PFX(LoadMicrocodeDefault)
 | |
| ASM_PFX(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
 | |
| 
 | |
|    ;
 | |
|    ;
 | |
|    ; Save return address to EBP
 | |
|    movd   ebp, mm7
 | |
| 
 | |
|    cmp    esp, 0
 | |
|    jz     ParamError
 | |
|    mov    eax, dword [esp + 4]    ; Parameter pointer
 | |
|    cmp    eax, 0
 | |
|    jz     ParamError
 | |
|    mov    esp, eax
 | |
| 
 | |
|    ; skip loading Microcode if the MicrocodeCodeSize is zero
 | |
|    ; and report error if size is less than 2k
 | |
|    ; first check UPD header revision
 | |
|    cmp    byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
 | |
|    jae    Fsp22UpdHeader
 | |
| 
 | |
|    ; UPD structure is compliant with FSP spec 2.0/2.1
 | |
|    mov    eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
 | |
|    cmp    eax, 0
 | |
|    jz     Exit2
 | |
|    cmp    eax, 0800h
 | |
|    jl     ParamError
 | |
| 
 | |
|    mov    esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
 | |
|    cmp    esi, 0
 | |
|    jnz    CheckMainHeader
 | |
|    jmp    ParamError
 | |
| 
 | |
| Fsp22UpdHeader:
 | |
|    ; UPD structure is compliant with FSP spec 2.2
 | |
|    mov    eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
 | |
|    cmp    eax, 0
 | |
|    jz     Exit2
 | |
|    cmp    eax, 0800h
 | |
|    jl     ParamError
 | |
| 
 | |
|    mov    esi, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
 | |
|    cmp    esi, 0
 | |
|    jnz    CheckMainHeader
 | |
| 
 | |
| ParamError:
 | |
|    mov    eax, 080000002h
 | |
|    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   LoadCheck  ; Jif signature and platform ID match
 | |
| 
 | |
| LoadMicrocodeDefault1:
 | |
|    ; Check if extended header exists
 | |
|    ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
 | |
|    xor   eax, eax
 | |
|    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   LoadCheck      ; 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   eax, eax
 | |
|    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 [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
 | |
|    jae    Fsp22UpdHeader1
 | |
| 
 | |
|    ; UPD structure is compliant with FSP spec 2.0/2.1
 | |
|    ; Is automatic size detection ?
 | |
|    mov   eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
 | |
|    cmp   eax, 0ffffffffh
 | |
|    jz    LoadMicrocodeDefault4
 | |
| 
 | |
|    ; Address >= microcode region address + microcode region size?
 | |
|    add   eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
 | |
|    cmp   esi, eax
 | |
|    jae   Done        ;Jif address is outside of microcode region
 | |
|    jmp   CheckMainHeader
 | |
| 
 | |
| Fsp22UpdHeader1:
 | |
|    ; UPD structure is compliant with FSP spec 2.2
 | |
|    ; Is automatic size detection ?
 | |
|    mov   eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
 | |
|    cmp   eax, 0ffffffffh
 | |
|    jz    LoadMicrocodeDefault4
 | |
| 
 | |
|    ; Address >= microcode region address + microcode region size?
 | |
|    add   eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
 | |
|    cmp   esi, eax
 | |
|    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
 | |
| 
 | |
| LoadCheck:
 | |
|    ; 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   dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
 | |
|    je    Continue
 | |
| 
 | |
| 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
 | |
| 
 | |
| Continue:
 | |
|    jmp   NextMicrocode
 | |
| 
 | |
| Done:
 | |
|    mov   eax, 1
 | |
|    cpuid
 | |
|    mov   ecx, MSR_IA32_BIOS_SIGN_ID
 | |
|    rdmsr                         ; Get current microcode signature
 | |
|    xor   eax, eax
 | |
|    cmp   edx, 0
 | |
|    jnz   Exit2
 | |
|    mov   eax, 08000000Eh
 | |
| 
 | |
| Exit2:
 | |
|    jmp   ebp
 | |
| 
 | |
| 
 | |
| global ASM_PFX(EstablishStackFsp)
 | |
| ASM_PFX(EstablishStackFsp):
 | |
|   ;
 | |
|   ; Save parameter pointer in edx
 | |
|   ;
 | |
|   mov       edx, dword [esp + 4]
 | |
| 
 | |
|   ;
 | |
|   ; Enable FSP STACK
 | |
|   ;
 | |
|   mov       esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
 | |
|   add       esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
 | |
| 
 | |
|   push      DATA_LEN_OF_MCUD     ; Size of the data region
 | |
|   push      4455434Dh            ; Signature of the  data region 'MCUD'
 | |
| 
 | |
|   ; check UPD structure revision (edx + 8)
 | |
|   cmp       byte [edx + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
 | |
|   jae       Fsp22UpdHeader2
 | |
| 
 | |
|   ; UPD structure is compliant with FSP spec 2.0/2.1
 | |
|   push      dword [edx + LoadMicrocodeParams.CodeRegionSize]     ; Code size       sizeof(FSPT_UPD_COMMON) + 12
 | |
|   push      dword [edx + LoadMicrocodeParams.CodeRegionBase]     ; Code base       sizeof(FSPT_UPD_COMMON) + 8
 | |
|   push      dword [edx + LoadMicrocodeParams.MicrocodeCodeSize]  ; Microcode size  sizeof(FSPT_UPD_COMMON) + 4
 | |
|   push      dword [edx + LoadMicrocodeParams.MicrocodeCodeAddr]  ; Microcode base  sizeof(FSPT_UPD_COMMON) + 0
 | |
|   jmp       ContinueAfterUpdPush
 | |
| 
 | |
| Fsp22UpdHeader2:
 | |
|   ; UPD structure is compliant with FSP spec 2.2
 | |
|   push      dword [edx + LoadMicrocodeParamsFsp22.CodeRegionSize]     ; Code size       sizeof(FSPT_UPD_COMMON) + 12
 | |
|   push      dword [edx + LoadMicrocodeParamsFsp22.CodeRegionBase]     ; Code base       sizeof(FSPT_UPD_COMMON) + 8
 | |
|   push      dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]  ; Microcode size  sizeof(FSPT_UPD_COMMON) + 4
 | |
|   push      dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]  ; Microcode base  sizeof(FSPT_UPD_COMMON) + 0
 | |
| 
 | |
| ContinueAfterUpdPush:
 | |
|   ;
 | |
|   ; 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'
 | |
|   rdtsc
 | |
|   push      edx
 | |
|   push      eax
 | |
|   LOAD_EDX
 | |
|   push      edx
 | |
|   LOAD_EAX
 | |
|   push      eax
 | |
| 
 | |
|   ;
 | |
|   ; Terminator for the data on stack
 | |
|   ;
 | |
|   push      0
 | |
| 
 | |
|   ;
 | |
|   ; Set ECX/EDX to the BootLoader temporary memory range
 | |
|   ;
 | |
|   mov       ecx,  [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
 | |
|   mov       edx, ecx
 | |
|   add       edx,  [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
 | |
|   sub       edx,  [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
 | |
| 
 | |
|   cmp       ecx, edx        ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
 | |
|   jb        EstablishStackFspSuccess
 | |
|   mov       eax, 80000003h  ;EFI_UNSUPPORTED
 | |
|   jmp       EstablishStackFspExit
 | |
| EstablishStackFspSuccess:
 | |
|   xor       eax, eax
 | |
| 
 | |
| EstablishStackFspExit:
 | |
|   RET_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.
 | |
| ;
 | |
| ;----------------------------------------------------------------------------
 | |
| 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
 | |
|   ;
 | |
|   mov       eax, dword [esp + 4]
 | |
|   cmp       eax, 0
 | |
|   mov       eax, 80000002h
 | |
|   jz        TempRamInitExit
 | |
| 
 | |
|   ;
 | |
|   ; Sec Platform Init
 | |
|   ;
 | |
|   CALL_MMX  ASM_PFX(SecPlatformInit)
 | |
|   cmp       eax, 0
 | |
|   jnz       TempRamInitExit
 | |
| 
 | |
|   ; Load microcode
 | |
|   LOAD_ESP
 | |
|   CALL_MMX  ASM_PFX(LoadMicrocodeDefault)
 | |
|   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  ASM_PFX(SecCarInit)
 | |
|   cmp       eax, 0
 | |
|   jnz       TempRamInitExit
 | |
| 
 | |
|   LOAD_ESP
 | |
|   CALL_MMX  ASM_PFX(EstablishStackFsp)
 | |
|   cmp       eax, 0
 | |
|   jnz       TempRamInitExit
 | |
| 
 | |
|   LXMMN      xmm6, eax, 3  ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
 | |
| 
 | |
| 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 EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
 | |
|   ;
 | |
|   LOAD_REGS
 | |
|   ret
 | |
| 
 | |
| ;----------------------------------------------------------------------------
 | |
| ; Module Entrypoint API
 | |
| ;----------------------------------------------------------------------------
 | |
| global ASM_PFX(_ModuleEntryPoint)
 | |
| ASM_PFX(_ModuleEntryPoint):
 | |
|   jmp $
 |