Fix FSP GCC error on FspApiCallingCheck().
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.s
CommitLineData
c8ec22a2
JY
1#------------------------------------------------------------------------------\r
2#\r
d5fb1edf 3# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
c8ec22a2
JY
4# This program and the accompanying materials\r
5# are licensed and made available under the terms and conditions of the BSD License\r
6# which accompanies this distribution. The full text of the license may be found at\r
7# http://opensource.org/licenses/bsd-license.php.\r
8#\r
9# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11#\r
12# Abstract:\r
13#\r
14# Provide FSP API entry points.\r
15#\r
16#------------------------------------------------------------------------------\r
17\r
975f1c64
JY
18\r
19.equ MSR_IA32_PLATFORM_ID, 0x00000017\r
20.equ MSR_IA32_BIOS_UPDT_TRIG, 0x00000079\r
21.equ MSR_IA32_BIOS_SIGN_ID, 0x0000008b\r
22\r
9da59186
JY
23\r
24MicrocodeHdr:\r
25.equ MicrocodeHdrVersion, 0x0000\r
26.equ MicrocodeHdrRevision, 0x0004\r
27.equ MicrocodeHdrDate, 0x0008\r
28.equ MicrocodeHdrProcessor, 0x000c\r
29.equ MicrocodeHdrChecksum, 0x0010\r
30.equ MicrocodeHdrLoader, 0x0014\r
31.equ MicrocodeHdrFlags, 0x0018\r
32.equ MicrocodeHdrDataSize, 0x001C\r
33.equ MicrocodeHdrTotalSize, 0x0020\r
34.equ MicrocodeHdrRsvd, 0x0024\r
35MicrocodeHdrEnd:\r
36.equ MicrocodeHdrLength, 0x0030 # MicrocodeHdrLength = MicrocodeHdrEnd - MicrocodeHdr\r
975f1c64
JY
37\r
38\r
39ExtSigHdr:\r
40.equ ExtSigHdrCount, 0x0000\r
41.equ ExtSigHdrChecksum, 0x0004\r
9da59186 42.equ ExtSigHdrRsvd, 0x0008\r
975f1c64
JY
43ExtSigHdrEnd:\r
44.equ ExtSigHdrLength, 0x0014 #ExtSigHdrLength = ExtSigHdrEnd - ExtSigHdr\r
45\r
46ExtSig:\r
47.equ ExtSigProcessor, 0x0000\r
48.equ ExtSigFlags, 0x0004\r
49.equ ExtSigChecksum, 0x0008\r
50ExtSigEnd:\r
51.equ ExtSigLength, 0x000C #ExtSigLength = ExtSigEnd - ExtSig\r
52\r
9da59186
JY
53LoadMicrocodeParams:\r
54.equ MicrocodeCodeAddr, 0x0000\r
55.equ MicrocodeCodeSize, 0x0004\r
56LoadMicrocodeParamsEnd:\r
975f1c64 57\r
975f1c64 58\r
c8ec22a2 59\r
975f1c64
JY
60.macro SAVE_REGS\r
61 pinsrw $0x00, %ebp, %xmm7\r
62 ror $0x10, %ebp\r
63 pinsrw $0x01, %ebp, %xmm7\r
64 ror $0x10, %ebp\r
c8ec22a2 65#\r
975f1c64
JY
66 pinsrw $0x02, %ebx, %xmm7\r
67 ror $0x10, %ebx\r
68 pinsrw $0x03, %ebx, %xmm7\r
69 ror $0x10, %ebx\r
c8ec22a2 70#\r
975f1c64
JY
71 pinsrw $0x04, %esi, %xmm7\r
72 ror $0x10, %esi\r
73 pinsrw $0x05, %esi, %xmm7\r
74 ror $0x10, %esi\r
c8ec22a2 75#\r
975f1c64
JY
76 pinsrw $0x06, %edi, %xmm7\r
77 ror $0x10, %edi\r
78 pinsrw $0x07, %edi, %xmm7\r
79 ror $0x10, %edi\r
c8ec22a2 80#\r
975f1c64
JY
81 pinsrw $0x00, %esp, %xmm6\r
82 ror $0x10, %esp\r
83 pinsrw $0x01, %esp, %xmm6\r
84 ror $0x10, %esp\r
85.endm\r
c8ec22a2 86\r
975f1c64
JY
87.macro LOAD_REGS\r
88 pshufd $0xe4, %xmm7, %xmm7\r
89 movd %xmm7, %ebp \r
90 pshufd $0xe4, %xmm7, %xmm7\r
c8ec22a2 91#\r
975f1c64
JY
92 pshufd $0x39, %xmm7, %xmm7\r
93 movd %xmm7, %ebx\r
94 pshufd $0x93, %xmm7, %xmm7\r
c8ec22a2 95#\r
975f1c64
JY
96 pshufd $0x4e, %xmm7, %xmm7\r
97 movd %xmm7, %esi\r
98 pshufd $0x4e, %xmm7, %xmm7\r
c8ec22a2 99#\r
975f1c64
JY
100 pshufd $0x93, %xmm7, %xmm7\r
101 movd %xmm7, %edi\r
102 pshufd $0x39, %xmm7, %xmm7\r
c8ec22a2 103#\r
975f1c64
JY
104 movd %xmm6, %esp\r
105.endm\r
c8ec22a2 106\r
975f1c64
JY
107.macro LOAD_EAX\r
108 pshufd $0x39, %xmm6, %xmm6\r
109 movd %xmm6, %eax\r
110 pshufd $0x93, %xmm6, %xmm6\r
c8ec22a2
JY
111.endm\r
112\r
975f1c64
JY
113.macro LOAD_EDX\r
114 pshufd $0xe4, %xmm6, %xmm6\r
115 movd %xmm6, %edx\r
116 pshufd $0xe4, %xmm6, %xmm6\r
c8ec22a2
JY
117.endm\r
118\r
975f1c64
JY
119.macro SAVE_EAX\r
120 pinsrw $0x02, %eax, %xmm6\r
121 ror $0x10, %eax\r
122 pinsrw $0x03, %eax, %xmm6\r
123 ror $0x10, %eax\r
124.endm\r
125\r
126.macro SAVE_EDX\r
127 pinsrw $0x04, %edx, %xmm6\r
128 ror $0x10, %edx\r
129 pinsrw $0x05, %edx, %xmm6\r
130 ror $0x10, %edx\r
c8ec22a2
JY
131.endm\r
132\r
133.macro LOAD_ESP\r
134 movd %xmm6, %esp\r
135.endm\r
136\r
975f1c64 137.macro ENABLE_SSE\r
9da59186
JY
138 jmp NextAddress\r
139.align 4\r
140 #\r
141 # Float control word initial value:\r
142 # all exceptions masked, double-precision, round-to-nearest\r
143 #\r
144ASM_PFX(mFpuControlWord): .word 0x027F\r
145 #\r
146 # Multimedia-extensions control word:\r
147 # all exceptions masked, round-to-nearest, flush to zero for masked underflow\r
148 #\r
149ASM_PFX(mMmxControlWord): .long 0x01F80\r
150SseError: \r
151 #\r
152 # Processor has to support SSE\r
153 #\r
154 jmp SseError \r
155NextAddress: \r
156 #\r
157 # Initialize floating point units\r
158 #\r
159 finit\r
160 fldcw ASM_PFX(mFpuControlWord)\r
161\r
162 #\r
163 # Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test\r
164 # whether the processor supports SSE instruction.\r
165 #\r
166 movl $1, %eax\r
167 cpuid\r
168 btl $25, %edx\r
169 jnc SseError\r
170\r
171 #\r
172 # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)\r
173 #\r
174 movl %cr4, %eax\r
175 orl $BIT9, %eax\r
176 movl %eax, %cr4\r
177\r
178 #\r
179 # The processor should support SSE instruction and we can use\r
180 # ldmxcsr instruction\r
181 #\r
182 ldmxcsr ASM_PFX(mMmxControlWord)\r
183.endm\r
184\r
185#Save in ECX-SLOT 3 in xmm6.\r
186.macro SAVE_EAX_MICROCODE_RET_STATUS\r
187 pinsrw $0x6, %eax, %xmm6\r
188 ror $0x10, %eax\r
189 pinsrw $0x7, %eax, %xmm6\r
190 rol $0x10, %eax\r
191.endm\r
192\r
193#Restore from ECX-SLOT 3 in xmm6.\r
194.macro LOAD_EAX_MICROCODE_RET_STATUS\r
195 pshufd $0x93, %xmm6, %xmm6\r
196 movd %xmm6, %eax\r
197 pshufd $0x39, %xmm6, %xmm6\r
975f1c64
JY
198.endm\r
199\r
975f1c64
JY
200\r
201\r
202#\r
203# Following are fixed PCDs\r
204#\r
205ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase)\r
206ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize)\r
207ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)\r
208\r
209#\r
210# Following functions will be provided in C\r
211#\r
975f1c64
JY
212ASM_GLOBAL ASM_PFX(SecStartup)\r
213ASM_GLOBAL ASM_PFX(FspApiCallingCheck)\r
214\r
215#\r
216# Following functions will be provided in PlatformSecLib\r
217#\r
16b7e82c
JY
218ASM_GLOBAL ASM_PFX(AsmGetFspBaseAddress)\r
219ASM_GLOBAL ASM_PFX(AsmGetFspInfoHeader)\r
975f1c64 220ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)\r
3b17b245 221ASM_GLOBAL ASM_PFX(Loader2PeiSwitchStack)\r
975f1c64
JY
222\r
223\r
224#\r
225# Define the data length that we saved on the stack top\r
226#\r
227.equ DATA_LEN_OF_PER0, 0x018\r
228.equ DATA_LEN_OF_MCUD, 0x018\r
229.equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)\r
230\r
975f1c64 231#------------------------------------------------------------------------------\r
c030e74c 232# SecPlatformInitDefault\r
975f1c64 233# Inputs:\r
1c54ceb7 234# mm7 -> Return address\r
975f1c64
JY
235# Outputs:\r
236# eax -> 0 - Successful, Non-zero - Failed.\r
237# Register Usage:\r
238# eax is cleared and ebp is used for return address.\r
239# All others reserved.\r
c8ec22a2 240#------------------------------------------------------------------------------\r
c030e74c
JY
241ASM_GLOBAL ASM_PFX(SecPlatformInitDefault)\r
242ASM_PFX(SecPlatformInitDefault):\r
975f1c64 243 #\r
c8ec22a2 244 # Save return address to EBP\r
975f1c64 245 #\r
1c54ceb7 246 movd %mm7, %ebp\r
c8ec22a2 247 xorl %eax, %eax\r
975f1c64 248\r
c030e74c 249SecPlatformInitDefaultExit:\r
c8ec22a2 250 jmp *%ebp\r
975f1c64 251\r
c8ec22a2 252\r
975f1c64 253#------------------------------------------------------------------------------\r
9da59186 254# LoadMicrocodeDefault\r
975f1c64
JY
255#\r
256# Inputs:\r
9da59186 257# esp -> LoadMicrocodeParams pointer\r
975f1c64
JY
258# Register Usage:\r
259# esp Preserved\r
260# All others destroyed\r
261# Assumptions:\r
262# No memory available, stack is hard-coded and used for return address\r
263# Executed by SBSP and NBSP\r
264# Beginning of microcode update region starts on paragraph boundary\r
c8ec22a2 265#------------------------------------------------------------------------------\r
9da59186
JY
266ASM_GLOBAL ASM_PFX(LoadMicrocodeDefault)\r
267ASM_PFX(LoadMicrocodeDefault):\r
c8ec22a2
JY
268 #\r
269 # Save return address to EBP\r
975f1c64 270 #\r
95c95ac0 271 movd %mm7, %ebp\r
d5fb1edf 272\r
975f1c64
JY
273 cmpl $0x00, %esp\r
274 jz ParamError\r
9da59186 275 movl 4(%esp), %eax #dword ptr [] Parameter pointer\r
975f1c64
JY
276 cmpl $0x00, %eax\r
277 jz ParamError\r
c8ec22a2 278 movl %eax, %esp\r
9da59186 279 movl MicrocodeCodeAddr(%esp), %esi\r
975f1c64
JY
280 cmpl $0x00, %esi\r
281 jnz CheckMainHeader\r
c8ec22a2 282\r
975f1c64
JY
283ParamError:\r
284 movl $0x080000002, %eax\r
9da59186 285 jmp LoadMicrocodeExit\r
c8ec22a2 286\r
975f1c64
JY
287CheckMainHeader:\r
288 #\r
c8ec22a2
JY
289 # Get processor signature and platform ID from the installed processor\r
290 # and save into registers for later use\r
291 # ebx = processor signature\r
292 # edx = platform ID\r
975f1c64
JY
293 #\r
294 movl $0x01, %eax\r
c8ec22a2
JY
295 cpuid\r
296 movl %eax, %ebx\r
975f1c64 297 movl $MSR_IA32_PLATFORM_ID, %ecx\r
c8ec22a2 298 rdmsr\r
975f1c64
JY
299 movl %edx, %ecx\r
300 shrl $0x12, %ecx #($50-$32)\r
301 andl $0x07, %ecx\r
302 movl $0x01, %edx\r
303 shll %cl,%edx\r
c8ec22a2 304\r
975f1c64 305 #\r
c8ec22a2
JY
306 # Current register usage\r
307 # esp -> stack with paramters\r
308 # esi -> microcode update to check\r
309 # ebx = processor signature\r
310 # edx = platform ID\r
975f1c64 311 #\r
c8ec22a2 312\r
975f1c64 313 #\r
c8ec22a2
JY
314 # Check for valid microcode header\r
315 # Minimal test checking for header version and loader version as 1\r
975f1c64
JY
316 #\r
317 movl $0x01, %eax\r
9da59186 318 cmpl %eax, MicrocodeHdrVersion(%esi)\r
975f1c64 319 jne AdvanceFixedSize\r
9da59186 320 cmpl %eax, MicrocodeHdrLoader(%esi)\r
975f1c64 321 jne AdvanceFixedSize\r
c8ec22a2 322\r
975f1c64 323 #\r
c8ec22a2 324 # Check if signature and plaform ID match\r
975f1c64 325 #\r
9da59186
JY
326 cmpl MicrocodeHdrProcessor(%esi), %ebx\r
327 jne LoadMicrocodeL0\r
328 testl MicrocodeHdrFlags(%esi), %edx\r
975f1c64 329 jnz LoadCheck #Jif signature and platform ID match\r
c8ec22a2 330\r
9da59186 331LoadMicrocodeL0:\r
975f1c64 332 #\r
c8ec22a2 333 # Check if extended header exists\r
9da59186 334 # First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid\r
975f1c64
JY
335 #\r
336 xorl %eax, %eax\r
9da59186 337 cmpl %eax, MicrocodeHdrTotalSize(%esi)\r
975f1c64 338 je NextMicrocode\r
9da59186 339 cmpl %eax, MicrocodeHdrDataSize(%esi)\r
975f1c64 340 je NextMicrocode\r
c8ec22a2 341\r
975f1c64 342 #\r
c8ec22a2 343 # Then verify total size - sizeof header > data size\r
975f1c64 344 #\r
9da59186
JY
345 movl MicrocodeHdrTotalSize(%esi), %ecx\r
346 subl $MicrocodeHdrLength, %ecx\r
347 cmpl MicrocodeHdrDataSize(%esi), %ecx\r
348 jle NextMicrocode\r
c8ec22a2 349\r
975f1c64 350 #\r
c8ec22a2 351 # Set edi -> extended header\r
975f1c64
JY
352 #\r
353 movl %esi, %edi\r
9da59186
JY
354 addl $MicrocodeHdrLength, %edi\r
355 addl MicrocodeHdrDataSize(%esi), %edi\r
c8ec22a2 356\r
975f1c64 357 #\r
c8ec22a2 358 # Get count of extended structures\r
975f1c64 359 #\r
9da59186 360 movl ExtSigHdrCount(%edi), %ecx\r
c8ec22a2 361\r
975f1c64 362 #\r
c8ec22a2 363 # Move pointer to first signature structure\r
975f1c64 364 #\r
9da59186 365 addl ExtSigHdrLength, %edi\r
c8ec22a2 366\r
975f1c64
JY
367CheckExtSig:\r
368 #\r
c8ec22a2 369 # Check if extended signature and platform ID match\r
975f1c64 370 #\r
9da59186
JY
371 cmpl %ebx, ExtSigProcessor(%edi)\r
372 jne LoadMicrocodeL1\r
373 test %edx, ExtSigFlags(%edi)\r
975f1c64 374 jnz LoadCheck # Jif signature and platform ID match\r
9da59186 375LoadMicrocodeL1:\r
975f1c64 376 #\r
c8ec22a2 377 # Check if any more extended signatures exist\r
975f1c64 378 #\r
9da59186 379 addl $ExtSigLength, %edi\r
975f1c64 380 loop CheckExtSig\r
c8ec22a2 381\r
975f1c64
JY
382NextMicrocode:\r
383 #\r
c8ec22a2 384 # Advance just after end of this microcode\r
975f1c64 385 #\r
c8ec22a2 386 xorl %eax, %eax\r
9da59186
JY
387 cmpl %eax, MicrocodeHdrTotalSize(%esi)\r
388 je LoadMicrocodeL2\r
389 addl MicrocodeHdrTotalSize(%esi), %esi\r
975f1c64 390 jmp CheckAddress\r
9da59186 391LoadMicrocodeL2:\r
975f1c64
JY
392 addl $0x800, %esi #add esi, dword ptr 2048\r
393 jmp CheckAddress\r
394\r
395AdvanceFixedSize:\r
396 #\r
c8ec22a2 397 # Advance by 4X dwords\r
975f1c64
JY
398 #\r
399 addl $0x400, %esi #add esi, dword ptr 1024\r
c8ec22a2 400\r
975f1c64
JY
401CheckAddress:\r
402 #\r
c8ec22a2 403 # Is valid Microcode start point ?\r
975f1c64 404 #\r
9da59186 405 cmpl $0x0ffffffff, MicrocodeHdrVersion(%esi)\r
c8ec22a2 406\r
975f1c64
JY
407 #\r
408 # Is automatic size detection ?\r
409 #\r
9da59186 410 movl MicrocodeCodeSize(%esp), %eax\r
975f1c64 411 cmpl $0x0ffffffff, %eax\r
9da59186 412 jz LoadMicrocodeL3\r
975f1c64 413 #\r
c8ec22a2 414 # Address >= microcode region address + microcode region size?\r
975f1c64 415 #\r
9da59186 416 addl MicrocodeCodeAddr(%esp), %eax\r
975f1c64 417\r
c8ec22a2 418 cmpl %eax, %esi\r
9da59186 419 jae Done #Jif address is outside of microcode region\r
975f1c64 420 jmp CheckMainHeader\r
c8ec22a2 421\r
9da59186 422LoadMicrocodeL3:\r
975f1c64
JY
423LoadCheck:\r
424 #\r
c8ec22a2 425 # Get the revision of the current microcode update loaded\r
975f1c64
JY
426 #\r
427 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
428 xorl %eax, %eax # Clear EAX\r
429 xorl %edx, %edx # Clear EDX\r
430 wrmsr # Load 0 to MSR at 8Bh\r
c8ec22a2 431\r
975f1c64 432 movl $0x01, %eax\r
c8ec22a2 433 cpuid\r
975f1c64
JY
434 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
435 rdmsr # Get current microcode signature\r
c8ec22a2 436\r
975f1c64 437 #\r
c8ec22a2 438 # Verify this microcode update is not already loaded\r
975f1c64 439 #\r
9da59186 440 cmpl %edx, MicrocodeHdrRevision(%esi)\r
975f1c64 441 je Continue\r
c8ec22a2 442\r
9da59186 443LoadMicrocode0:\r
975f1c64 444 #\r
c8ec22a2
JY
445 # EAX contains the linear address of the start of the Update Data\r
446 # EDX contains zero\r
447 # ECX contains 79h (IA32_BIOS_UPDT_TRIG)\r
448 # Start microcode load with wrmsr\r
975f1c64
JY
449 #\r
450 movl %esi, %eax\r
9da59186 451 addl $MicrocodeHdrLength, %eax\r
975f1c64
JY
452 xorl %edx, %edx\r
453 movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx\r
c8ec22a2 454 wrmsr\r
975f1c64 455 movl $0x01, %eax\r
c8ec22a2
JY
456 cpuid\r
457\r
975f1c64
JY
458Continue:\r
459 jmp NextMicrocode\r
c8ec22a2 460\r
975f1c64
JY
461Done:\r
462 movl $0x01, %eax\r
c8ec22a2 463 cpuid\r
975f1c64
JY
464 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
465 rdmsr # Get current microcode signature\r
c8ec22a2 466 xorl %eax, %eax\r
975f1c64 467 cmpl $0x00, %edx\r
9da59186 468 jnz LoadMicrocodeExit\r
975f1c64 469 movl $0x08000000E, %eax\r
c8ec22a2 470\r
9da59186 471LoadMicrocodeExit:\r
c8ec22a2
JY
472 jmp *%ebp\r
473\r
c8ec22a2 474\r
d5fb1edf
JY
475#----------------------------------------------------------------------------\r
476# EstablishStackFsp\r
477#\r
d5fb1edf
JY
478#----------------------------------------------------------------------------\r
479ASM_GLOBAL ASM_PFX(EstablishStackFsp)\r
480ASM_PFX(EstablishStackFsp):\r
481 #\r
9da59186 482 # Save parameter pointer in edx\r
d5fb1edf
JY
483 #\r
484 movl 4(%esp), %edx\r
9da59186 485\r
d5fb1edf
JY
486 #\r
487 # Enable FSP STACK\r
488 #\r
489 movl PcdGet32(PcdTemporaryRamBase), %esp\r
490 addl PcdGet32(PcdTemporaryRamSize), %esp\r
491\r
492 pushl $DATA_LEN_OF_MCUD # Size of the data region\r
493 pushl $0x4455434D # Signature of the data region 'MCUD'\r
494 pushl 12(%edx) # Code size\r
495 pushl 8(%edx) # Code base\r
d5fb1edf
JY
496 pushl 4(%edx) # Microcode size\r
497 pushl (%edx) # Microcode base\r
d5fb1edf 498\r
d5fb1edf
JY
499 #\r
500 # Save API entry/exit timestamp into stack\r
501 #\r
502 pushl $DATA_LEN_OF_PER0 # Size of the data region\r
503 pushl $0x30524550 # Signature of the data region 'PER0'\r
95c95ac0
JY
504 LOAD_EDX\r
505 pushl %edx\r
506 LOAD_EAX\r
d5fb1edf
JY
507 pushl %eax\r
508 rdtsc\r
509 pushl %edx\r
510 pushl %eax\r
511\r
512 #\r
513 # Terminator for the data on stack\r
9da59186 514 #\r
d5fb1edf
JY
515 push $0x00\r
516\r
517 #\r
9da59186 518 # Set ECX/EDX to the BootLoader temporary memory range\r
d5fb1edf
JY
519 #\r
520 movl PcdGet32 (PcdTemporaryRamBase), %ecx\r
521 movl %ecx, %edx\r
522 addl PcdGet32 (PcdTemporaryRamSize), %edx\r
523 subl PcdGet32 (PcdFspTemporaryRamSize), %edx\r
524\r
525 xorl %eax, %eax\r
9da59186 526\r
d5fb1edf
JY
527 movd %mm7, %esi #RET_ESI\r
528 jmp *%esi\r
529\r
c8ec22a2
JY
530#----------------------------------------------------------------------------\r
531# TempRamInit API\r
532#\r
533# This FSP API will load the microcode update, enable code caching for the\r
534# region specified by the boot loader and also setup a temporary stack to be\r
535# used till main memory is initialized.\r
536#\r
537#----------------------------------------------------------------------------\r
538ASM_GLOBAL ASM_PFX(TempRamInitApi)\r
539ASM_PFX(TempRamInitApi):\r
540 #\r
541 # Ensure SSE is enabled\r
542 #\r
543 ENABLE_SSE\r
544\r
545 #\r
546 # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6\r
547 #\r
548 SAVE_REGS\r
549\r
550 #\r
1c54ceb7 551 # Save timestamp into XMM6\r
c8ec22a2
JY
552 #\r
553 rdtsc\r
95c95ac0
JY
554 SAVE_EAX\r
555 SAVE_EDX\r
556\r
557 #\r
558 # Check Parameter\r
559 #\r
560 movl 4(%esp), %eax\r
561 cmpl $0x00, %eax\r
562 movl $0x80000002, %eax\r
563 jz NemInitExit\r
c8ec22a2
JY
564\r
565 #\r
3b17b245 566 # Sec Platform Init\r
c8ec22a2 567 #\r
d5fb1edf 568 movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit\r
9da59186
JY
569 movd %esi, %mm7\r
570 .weak ASM_PFX(SecPlatformInit)\r
571 .set ASM_PFX(SecPlatformInit), ASM_PFX(SecPlatformInitDefault)\r
d5fb1edf 572 jmp ASM_PFX(SecPlatformInit)\r
975f1c64 573TempRamInitApiL1:\r
95c95ac0
JY
574 cmpl $0x00, %eax\r
575 jnz NemInitExit\r
c8ec22a2
JY
576\r
577 #\r
95c95ac0 578 # Load microcode\r
c8ec22a2 579 #\r
95c95ac0 580 LOAD_ESP\r
9da59186
JY
581 movl $TempRamInitApiL2, %esi #CALL_MMX LoadMicrocode\r
582 movd %esi, %mm7\r
583 .weak ASM_PFX(LoadMicrocode)\r
584 .set ASM_PFX(LoadMicrocode), ASM_PFX(LoadMicrocodeDefault)\r
585 jmp ASM_PFX(LoadMicrocode)\r
975f1c64 586TempRamInitApiL2:\r
9da59186
JY
587 SAVE_EAX_MICROCODE_RET_STATUS #Save microcode return status in ECX-SLOT 3 in xmm6.\r
588 #@note If return value eax is not 0, microcode did not load, but continue and attempt to boot from ECX-SLOT 3 in xmm6.\r
c8ec22a2
JY
589\r
590 #\r
95c95ac0 591 # Call Sec CAR Init\r
c8ec22a2 592 #\r
95c95ac0
JY
593 LOAD_ESP\r
594 movl $TempRamInitApiL3, %esi #CALL_MMX SecCarInit\r
9da59186 595 movd %esi, %mm7\r
95c95ac0 596 jmp ASM_PFX(SecCarInit)\r
d5fb1edf 597TempRamInitApiL3:\r
95c95ac0
JY
598 cmpl $0x00, %eax\r
599 jnz NemInitExit\r
c8ec22a2
JY
600\r
601 #\r
d5fb1edf 602 # EstablishStackFsp\r
c8ec22a2 603 #\r
95c95ac0 604 LOAD_ESP\r
d5fb1edf 605 movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp\r
9da59186 606 movd %esi, %mm7\r
d5fb1edf
JY
607 jmp ASM_PFX(EstablishStackFsp)\r
608TempRamInitApiL4:\r
c8ec22a2 609\r
9da59186
JY
610 LOAD_EAX_MICROCODE_RET_STATUS #Restore microcode status if no CAR init error.\r
611\r
c8ec22a2
JY
612NemInitExit:\r
613 #\r
614 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6\r
615 #\r
616 LOAD_REGS\r
617 ret\r
975f1c64 618\r
9da59186 619\r
c8ec22a2
JY
620#----------------------------------------------------------------------------\r
621# FspInit API\r
622#\r
623# This FSP API will perform the processor and chipset initialization.\r
624# This API will not return. Instead, it transfers the control to the\r
625# ContinuationFunc provided in the parameter.\r
626#\r
627#----------------------------------------------------------------------------\r
628ASM_GLOBAL ASM_PFX(FspInitApi)\r
629ASM_PFX(FspInitApi):\r
d5fb1edf
JY
630 movl $0x01, %eax\r
631 jmp FspApiCommon\r
632\r
633#----------------------------------------------------------------------------\r
634# NotifyPhase API\r
635#\r
636# This FSP API will notify the FSP about the different phases in the boot\r
637# process\r
638#\r
639#----------------------------------------------------------------------------\r
640ASM_GLOBAL ASM_PFX(NotifyPhaseApi)\r
641ASM_PFX(NotifyPhaseApi):\r
642 movl $0x02, %eax\r
643 jmp FspApiCommon\r
644\r
645#----------------------------------------------------------------------------\r
646# FspMemoryInit API\r
647#\r
648# This FSP API is called after TempRamInit and initializes the memory.\r
649#\r
650#----------------------------------------------------------------------------\r
651ASM_GLOBAL ASM_PFX(FspMemoryInitApi)\r
652ASM_PFX(FspMemoryInitApi):\r
653 movl $0x03, %eax\r
654 jmp FspApiCommon\r
655\r
656#----------------------------------------------------------------------------\r
657# TempRamExitApi API\r
658#\r
659# This API tears down temporary RAM\r
660#\r
661#----------------------------------------------------------------------------\r
662ASM_GLOBAL ASM_PFX(TempRamExitApi)\r
663ASM_PFX(TempRamExitApi):\r
664 movl $0x04, %eax\r
665 jmp FspApiCommon\r
666\r
667#----------------------------------------------------------------------------\r
668# FspSiliconInit API\r
669#\r
670# This FSP API initializes the CPU and the chipset including the IO\r
671# controllers in the chipset to enable normal operation of these devices.\r
672#\r
673#----------------------------------------------------------------------------\r
674ASM_GLOBAL ASM_PFX(FspSiliconInitApi)\r
675ASM_PFX(FspSiliconInitApi):\r
676 movl $0x05, %eax\r
677 jmp FspApiCommon\r
678\r
679#----------------------------------------------------------------------------\r
680# FspApiCommon API\r
681#\r
682# This is the FSP API common entry point to resume the FSP execution\r
683#\r
684#----------------------------------------------------------------------------\r
685ASM_GLOBAL ASM_PFX(FspApiCommon)\r
686ASM_PFX(FspApiCommon):\r
c8ec22a2 687 #\r
d5fb1edf 688 # EAX holds the API index\r
c8ec22a2 689 #\r
d5fb1edf
JY
690\r
691 #\r
692 # Stack must be ready\r
693 # \r
694 pushl %eax\r
695 addl $0x04, %esp\r
696 cmpl -4(%esp), %eax\r
697 jz FspApiCommonL0\r
c8ec22a2 698 movl $0x080000003, %eax\r
d5fb1edf 699 jmp FspApiCommonExit\r
c8ec22a2 700\r
d5fb1edf 701FspApiCommonL0:\r
c8ec22a2 702 #\r
d5fb1edf 703 # Verify the calling condition\r
c8ec22a2 704 #\r
d5fb1edf 705 pushal\r
12a92f51
JY
706 pushl 36(%esp) #push ApiParam [esp + 4 * 8 + 4]\r
707 pushl %eax #push ApiIdx\r
c8ec22a2 708 call ASM_PFX(FspApiCallingCheck)\r
12a92f51 709 addl $0x08, %esp\r
975f1c64 710 cmpl $0x00, %eax\r
d5fb1edf
JY
711 jz FspApiCommonL1\r
712 movl %eax, 0x1C(%esp) # mov dword ptr [esp + 4 * 7], eax\r
713 popal\r
714 ret\r
715\r
716FspApiCommonL1:\r
717 popal\r
718 cmpl $0x01, %eax # FspInit API\r
719 jz FspApiCommonL2\r
720 cmpl $0x03, %eax # FspMemoryInit API\r
721 jz FspApiCommonL2\r
16b7e82c 722 call ASM_PFX(AsmGetFspInfoHeader)\r
3b17b245 723 jmp Loader2PeiSwitchStack\r
c8ec22a2 724\r
d5fb1edf
JY
725FspApiCommonL2:\r
726 #\r
727 # FspInit and FspMemoryInit APIs, setup the initial stack frame\r
728 # \r
729 \r
c8ec22a2 730 #\r
3b17b245 731 # Place holder to store the FspInfoHeader pointer\r
c8ec22a2 732 #\r
3b17b245
MM
733 pushl %eax\r
734\r
735 #\r
736 # Update the FspInfoHeader pointer\r
737 #\r
738 pushl %eax\r
16b7e82c 739 call ASM_PFX(AsmGetFspInfoHeader)\r
3b17b245
MM
740 movl %eax, 4(%esp)\r
741 popl %eax\r
c8ec22a2
JY
742\r
743 #\r
744 # Create a Task Frame in the stack for the Boot Loader\r
745 #\r
d5fb1edf 746 pushfl # 2 pushf for 4 byte alignment\r
c8ec22a2
JY
747 cli\r
748 pushal\r
749\r
975f1c64 750 #\r
c8ec22a2 751 # Reserve 8 bytes for IDT save/restore\r
975f1c64
JY
752 #\r
753 subl $0x08, %esp\r
754 sidt (%esp)\r
c8ec22a2
JY
755\r
756 #\r
757 # Setup new FSP stack\r
758 #\r
d5fb1edf
JY
759 movl %esp, %edi\r
760 movl PcdGet32(PcdTemporaryRamBase), %esp\r
761 addl PcdGet32(PcdTemporaryRamSize), %esp\r
975f1c64 762 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp\r
c8ec22a2 763\r
c8ec22a2 764 #\r
d5fb1edf
JY
765 # Pass the API Idx to SecStartup\r
766 #\r
767 pushl %eax\r
768 \r
769 #\r
9da59186 770 # Pass the BootLoader stack to SecStartup\r
d5fb1edf
JY
771 #\r
772 pushl %edi\r
c8ec22a2
JY
773\r
774 #\r
775 # Pass entry point of the PEI core\r
776 #\r
16b7e82c 777 call ASM_PFX(AsmGetFspBaseAddress)\r
d5fb1edf
JY
778 movl %eax, %edi\r
779 addl PcdGet32(PcdFspAreaSize), %edi\r
780 subl $0x20, %edi\r
781 addl %ds:(%edi), %eax\r
782 pushl %eax\r
c8ec22a2
JY
783\r
784 #\r
785 # Pass BFV into the PEI Core\r
786 # It uses relative address to calucate the actual boot FV base\r
787 # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and\r
788 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,\r
789 # they are different. The code below can handle both cases.\r
790 #\r
16b7e82c 791 call ASM_PFX(AsmGetFspBaseAddress)\r
d5fb1edf
JY
792 movl %eax, %edi\r
793 call ASM_PFX(GetBootFirmwareVolumeOffset)\r
794 addl %edi, %eax\r
795 pushl %eax\r
c8ec22a2
JY
796\r
797 #\r
798 # Pass stack base and size into the PEI Core\r
799 #\r
d5fb1edf
JY
800 movl PcdGet32(PcdTemporaryRamBase), %eax\r
801 addl PcdGet32(PcdTemporaryRamSize), %eax\r
802 subl PcdGet32(PcdFspTemporaryRamSize), %eax\r
803 pushl %eax\r
804 pushl PcdGet32(PcdFspTemporaryRamSize)\r
c8ec22a2
JY
805\r
806 #\r
807 # Pass Control into the PEI Core\r
808 #\r
809 call ASM_PFX(SecStartup)\r
3b17b245 810 addl $4, %esp\r
d5fb1edf 811FspApiCommonExit:\r
c8ec22a2
JY
812 ret\r
813\r