1 #------------------------------------------------------------------------------
3 # Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
4 # This program and the accompanying materials
5 # are licensed and made available under the terms and conditions of the BSD License
6 # which accompanies this distribution. The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php.
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 # Provide FSP API entry points.
16 #------------------------------------------------------------------------------
18 #.INCLUDE "UcodeLoadGcc.inc" - begin
20 .equ MSR_IA32_PLATFORM_ID, 0x00000017
21 .equ MSR_IA32_BIOS_UPDT_TRIG, 0x00000079
22 .equ MSR_IA32_BIOS_SIGN_ID, 0x0000008b
25 .equ UcodeVersion, 0x0000
26 .equ UcodeRevision, 0x0004
27 .equ UcodeDate, 0x0008
28 .equ UcodeProcessor, 0x000C
29 .equ UcodeChecksum, 0x0010
30 .equ UcodeLoader, 0x0014
31 .equ UcodeRsvd, 0x0018
35 .equ UcodeHdrVersion, 0x0000
36 .equ UcodeHdrRevision, 0x0004
37 .equ UcodeHdrDate, 0x0008
38 .equ UcodeHdrProcessor, 0x000c
39 .equ UcodeHdrChecksum, 0x0010
40 .equ UcodeHdrLoader, 0x0014
41 .equ UcodeHdrFlags, 0x0018
42 .equ UcodeHdrDataSize, 0x001C
43 .equ UcodeHdrTotalSize, 0x0020
44 .equ UcodeHdrRsvd, 0x0024
46 .equ UcodeHdrLength, 0x0030 # UcodeHdrLength = UcodeHdrEnd - UcodeHdr
50 .equ ExtSigHdrCount, 0x0000
51 .equ ExtSigHdrChecksum, 0x0004
54 .equ ExtSigHdrLength, 0x0014 #ExtSigHdrLength = ExtSigHdrEnd - ExtSigHdr
57 .equ ExtSigProcessor, 0x0000
58 .equ ExtSigFlags, 0x0004
59 .equ ExtSigChecksum, 0x0008
61 .equ ExtSigLength, 0x000C #ExtSigLength = ExtSigEnd - ExtSig
64 .equ LoadUcodeParamsUcodeCodeAddr, 0x0000
65 .equ LoadUcodeParamsUcodeCodeSize, 0x0004
68 #.INCLUDE "UcodeLoadGcc.inc" - end
70 #.INCLUDE "SaveRestoreSseGcc.inc" - begin
73 pinsrw $0x00, %ebp, %xmm7
75 pinsrw $0x01, %ebp, %xmm7
78 pinsrw $0x02, %ebx, %xmm7
80 pinsrw $0x03, %ebx, %xmm7
83 pinsrw $0x04, %esi, %xmm7
85 pinsrw $0x05, %esi, %xmm7
88 pinsrw $0x06, %edi, %xmm7
90 pinsrw $0x07, %edi, %xmm7
93 pinsrw $0x00, %esp, %xmm6
95 pinsrw $0x01, %esp, %xmm6
100 pshufd $0xe4, %xmm7, %xmm7
102 pshufd $0xe4, %xmm7, %xmm7
104 pshufd $0x39, %xmm7, %xmm7
106 pshufd $0x93, %xmm7, %xmm7
108 pshufd $0x4e, %xmm7, %xmm7
110 pshufd $0x4e, %xmm7, %xmm7
112 pshufd $0x93, %xmm7, %xmm7
114 pshufd $0x39, %xmm7, %xmm7
120 pshufd $0x39, %xmm6, %xmm6
122 pshufd $0x93, %xmm6, %xmm6
126 pshufd $0xe4, %xmm6, %xmm6
128 pshufd $0xe4, %xmm6, %xmm6
132 pinsrw $0x02, %eax, %xmm6
134 pinsrw $0x03, %eax, %xmm6
139 pinsrw $0x04, %edx, %xmm6
141 pinsrw $0x05, %edx, %xmm6
151 orl $0x00000600, %eax # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
155 #.INCLUDE "SaveRestoreSseGcc.inc" - end
159 # Following are fixed PCDs
161 ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase)
162 ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize)
163 ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
166 # Following functions will be provided in C
168 ASM_GLOBAL ASM_PFX(FspImageSizeOffset)
169 ASM_GLOBAL ASM_PFX(SecStartup)
170 ASM_GLOBAL ASM_PFX(FspApiCallingCheck)
173 # Following functions will be provided in PlatformSecLib
175 ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)
176 ASM_GLOBAL ASM_PFX(Pei2LoaderSwitchStack)
180 # Define the data length that we saved on the stack top
182 .equ DATA_LEN_OF_PER0, 0x018
183 .equ DATA_LEN_OF_MCUD, 0x018
184 .equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
186 #------------------------------------------------------------------------------
189 # eax -> Return address
191 # eax -> 0 - Successful, Non-zero - Failed.
193 # eax is cleared and ebp is used for return address.
194 # All others reserved.
195 #------------------------------------------------------------------------------
196 ASM_GLOBAL ASM_PFX(FspSelfCheckDflt)
197 ASM_PFX(FspSelfCheckDflt):
199 # Save return address to EBP
204 FspSelfCheckDfltExit:
208 #------------------------------------------------------------------------------
209 # PlatformBasicInitDflt
211 # eax -> Return address
213 # eax -> 0 - Successful, Non-zero - Failed.
215 # eax is cleared and ebp is used for return address.
216 # All others reserved.
217 #------------------------------------------------------------------------------
218 ASM_GLOBAL ASM_PFX(PlatformBasicInitDflt)
219 ASM_PFX(PlatformBasicInitDflt):
221 # Save return address to EBP
226 PlatformBasicInitDfltExit:
230 #------------------------------------------------------------------------------
234 # esp -> LOAD_UCODE_PARAMS pointer
237 # All others destroyed
239 # No memory available, stack is hard-coded and used for return address
240 # Executed by SBSP and NBSP
241 # Beginning of microcode update region starts on paragraph boundary
242 #------------------------------------------------------------------------------
243 ASM_GLOBAL ASM_PFX(LoadUcode)
246 # Save return address to EBP
251 movl (%esp), %eax #dword ptr [] Parameter pointer
255 movl LoadUcodeParamsUcodeCodeAddr(%esp), %esi #mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
260 movl $0x080000002, %eax
265 # Get processor signature and platform ID from the installed processor
266 # and save into registers for later use
267 # ebx = processor signature
273 movl $MSR_IA32_PLATFORM_ID, %ecx
276 shrl $0x12, %ecx #($50-$32)
282 # Current register usage
283 # esp -> stack with paramters
284 # esi -> microcode update to check
285 # ebx = processor signature
290 # Check for valid microcode header
291 # Minimal test checking for header version and loader version as 1
294 cmpl %eax, UcodeHdrVersion(%esi) #cmp [esi].ucode_hdr.version, eax
296 cmpl %eax, UcodeHdrLoader(%esi) #cmp [esi].ucode_hdr.loader, eax
300 # Check if signature and plaform ID match
302 cmpl UcodeHdrProcessor(%esi), %ebx #cmp ebx, [esi].ucode_hdr.processor
304 testl UcodeHdrFlags(%esi), %edx #test edx, [esi].ucode_hdr.flags
305 jnz LoadCheck #Jif signature and platform ID match
309 # Check if extended header exists
310 # First check if total_size and data_size are valid
313 cmpl %eax, UcodeHdrTotalSize(%esi) #cmp [esi].ucode_hdr.total_size, eax
315 cmpl %eax, UcodeHdrDataSize(%esi) #cmp [esi].ucode_hdr.data_size, eax
319 # Then verify total size - sizeof header > data size
321 movl UcodeHdrTotalSize(%esi), %ecx #mov ecx, [esi].ucode_hdr.total_size
322 subl $UcodeHdrLength, %ecx #sub ecx, sizeof ucode_hdr
323 cmpl UcodeHdrDataSize(%esi), %ecx #cmp ecx, [esi].ucode_hdr.data_size
327 # Set edi -> extended header
330 addl $UcodeHdrLength, %edi #add edi, sizeof ucode_hdr
331 addl UcodeHdrDataSize(%esi), %edi #add edi, [esi].ucode_hdr.data_size
334 # Get count of extended structures
336 movl ExtSigHdrCount(%edi), %ecx #mov ecx, [edi].ext_sig_hdr.count
339 # Move pointer to first signature structure
341 addl ExtSigHdrLength, %edi #add edi, sizeof ext_sig_hdr
345 # Check if extended signature and platform ID match
347 cmpl %ebx, ExtSigProcessor(%edi) #cmp [edi].ext_sig.processor, ebx
349 test %edx, ExtSigFlags(%edi) #test [edi].ext_sig.flags, edx
350 jnz LoadCheck # Jif signature and platform ID match
353 # Check if any more extended signatures exist
355 addl $ExtSigLength, %edi #add edi, sizeof ext_sig
360 # Advance just after end of this microcode
363 cmpl %eax, UcodeHdrTotalSize(%esi) #cmp [esi].ucode_hdr.total_size, eax
365 addl UcodeHdrTotalSize(%esi), %esi #add esi, [esi].ucode_hdr.total_size
368 addl $0x800, %esi #add esi, dword ptr 2048
373 # Advance by 4X dwords
375 addl $0x400, %esi #add esi, dword ptr 1024
379 # Is valid Microcode start point ?
381 cmpl $0x0ffffffff, UcodeHdrVersion(%esi)
384 # Is automatic size detection ?
386 movl LoadUcodeParamsUcodeCodeSize(%esp), %eax
387 cmpl $0x0ffffffff, %eax
390 # Address >= microcode region address + microcode region size?
392 addl LoadUcodeParamsUcodeCodeAddr(%esp), %eax #mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
395 jae Done #Jif address is outside of ucode region
401 # Get the revision of the current microcode update loaded
403 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
404 xorl %eax, %eax # Clear EAX
405 xorl %edx, %edx # Clear EDX
406 wrmsr # Load 0 to MSR at 8Bh
410 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
411 rdmsr # Get current microcode signature
414 # Verify this microcode update is not already loaded
416 cmpl %edx, UcodeHdrRevision(%esi) #cmp [esi].ucode_hdr.revision, edx
421 # EAX contains the linear address of the start of the Update Data
423 # ECX contains 79h (IA32_BIOS_UPDT_TRIG)
424 # Start microcode load with wrmsr
427 addl $UcodeHdrLength, %eax #add eax, sizeof ucode_hdr
429 movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx
440 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
441 rdmsr # Get current microcode signature
445 movl $0x08000000E, %eax
451 #----------------------------------------------------------------------------
454 # This FSP API will load the microcode update, enable code caching for the
455 # region specified by the boot loader and also setup a temporary stack to be
456 # used till main memory is initialized.
458 #----------------------------------------------------------------------------
459 ASM_GLOBAL ASM_PFX(TempRamInitApi)
460 ASM_PFX(TempRamInitApi):
462 # Ensure SSE is enabled
467 # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
472 # Save timestamp into XMM4 & XMM5
483 movl $0x80000002, %eax
487 # CPUID/DeviceID check
489 movl $TempRamInitApiL0, %eax
490 jmp ASM_PFX(FspSelfCheckDflt) # Note: ESP can not be changed.
496 # Platform Basic Init.
498 movl $TempRamInitApiL1, %eax
499 jmp ASM_PFX(PlatformBasicInitDflt)
507 movl $TempRamInitApiL2, %eax
517 # Call platform NEM init
519 movl $TempRamInitApiL3, %eax
521 jmp ASM_PFX(PlatformTempRamInit)
528 # Save parameter pointer in edx
535 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp
536 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %esp
538 pushl $DATA_LEN_OF_MCUD # Size of the data region
539 pushl $0x4455434D # Signature of the data region 'MCUD'
540 pushl 4(%edx) # Microcode size
541 pushl (%edx) # Microcode base
542 pushl 12(%edx) # Code size
543 pushl 8(%edx) # Code base
546 # Save API entry/exit timestamp into stack
548 pushl $DATA_LEN_OF_PER0 # Size of the data region
549 pushl $0x30524550 # Signature of the data region 'PER0'
559 # Terminator for the data on stack
564 # Set ECX/EDX to the bootloader temporary memory range
566 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %ecx
568 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %edx
569 subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %edx
575 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
581 #----------------------------------------------------------------------------
584 # This FSP API will perform the processor and chipset initialization.
585 # This API will not return. Instead, it transfers the control to the
586 # ContinuationFunc provided in the parameter.
588 #----------------------------------------------------------------------------
589 ASM_GLOBAL ASM_PFX(FspInitApi)
592 # Stack must be ready
596 cmpl $0x087654321, %eax
598 movl $0x080000003, %eax
607 call ASM_PFX(FspApiCallingCheck)
617 # Store the address in FSP which will return control to the BL
619 pushl $FspInitApiexit
622 # Create a Task Frame in the stack for the Boot Loader
624 pushfl # 2 pushf for 4 byte alignment
629 # Reserve 8 bytes for IDT save/restore
635 # Setup new FSP stack
638 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp
639 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %esp
640 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp
642 # Save the bootloader's stack pointer
647 # Pass entry point of the PEI core
649 call ASM_PFX(GetFspBaseAddress)
650 movl ASM_PFX(FspImageSizeOffset), %edi
651 movl (%eax, %edi), %edi
658 # Pass BFV into the PEI Core
659 # It uses relative address to calucate the actual boot FV base
660 # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
661 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
662 # they are different. The code below can handle both cases.
664 call ASM_PFX(GetFspBaseAddress)
666 call ASM_PFX(GetBootFirmwareVolumeOffset)
671 # Pass stack base and size into the PEI Core
673 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %eax
674 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %eax
675 subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %eax
677 pushl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
680 # Pass Control into the PEI Core
682 call ASM_PFX(SecStartup)
688 #----------------------------------------------------------------------------
691 # This FSP API will notify the FSP about the different phases in the boot
694 #----------------------------------------------------------------------------
695 ASM_GLOBAL ASM_PFX(NotifyPhaseApi)
696 ASM_PFX(NotifyPhaseApi):
698 # Stack must be ready
702 cmpl $0x087654321, %eax
704 movl $0x080000003, %eax
705 jmp NotifyPhaseApiErrExit
709 # Verify the calling condition
713 call ASM_PFX(FspApiCallingCheck)
724 NotifyPhaseApiErrExit:
728 jmp ASM_PFX(Pei2LoaderSwitchStack)