]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
Update IntelFspPkg to support FSP1.1
[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
218ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)\r
219ASM_GLOBAL ASM_PFX(Pei2LoaderSwitchStack)\r
220\r
221\r
222#\r
223# Define the data length that we saved on the stack top\r
224#\r
225.equ DATA_LEN_OF_PER0, 0x018\r
226.equ DATA_LEN_OF_MCUD, 0x018\r
227.equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)\r
228\r
975f1c64 229#------------------------------------------------------------------------------\r
c030e74c 230# SecPlatformInitDefault\r
975f1c64 231# Inputs:\r
1c54ceb7 232# mm7 -> Return address\r
975f1c64
JY
233# Outputs:\r
234# eax -> 0 - Successful, Non-zero - Failed.\r
235# Register Usage:\r
236# eax is cleared and ebp is used for return address.\r
237# All others reserved.\r
c8ec22a2 238#------------------------------------------------------------------------------\r
c030e74c
JY
239ASM_GLOBAL ASM_PFX(SecPlatformInitDefault)\r
240ASM_PFX(SecPlatformInitDefault):\r
975f1c64 241 #\r
c8ec22a2 242 # Save return address to EBP\r
975f1c64 243 #\r
1c54ceb7 244 movd %mm7, %ebp\r
c8ec22a2 245 xorl %eax, %eax\r
975f1c64 246\r
c030e74c 247SecPlatformInitDefaultExit:\r
c8ec22a2 248 jmp *%ebp\r
975f1c64 249\r
c8ec22a2 250\r
975f1c64 251#------------------------------------------------------------------------------\r
9da59186 252# LoadMicrocodeDefault\r
975f1c64
JY
253#\r
254# Inputs:\r
9da59186 255# esp -> LoadMicrocodeParams pointer\r
975f1c64
JY
256# Register Usage:\r
257# esp Preserved\r
258# All others destroyed\r
259# Assumptions:\r
260# No memory available, stack is hard-coded and used for return address\r
261# Executed by SBSP and NBSP\r
262# Beginning of microcode update region starts on paragraph boundary\r
c8ec22a2 263#------------------------------------------------------------------------------\r
9da59186
JY
264ASM_GLOBAL ASM_PFX(LoadMicrocodeDefault)\r
265ASM_PFX(LoadMicrocodeDefault):\r
c8ec22a2
JY
266 #\r
267 # Save return address to EBP\r
975f1c64 268 #\r
95c95ac0 269 movd %mm7, %ebp\r
d5fb1edf 270\r
975f1c64
JY
271 cmpl $0x00, %esp\r
272 jz ParamError\r
9da59186 273 movl 4(%esp), %eax #dword ptr [] Parameter pointer\r
975f1c64
JY
274 cmpl $0x00, %eax\r
275 jz ParamError\r
c8ec22a2 276 movl %eax, %esp\r
9da59186 277 movl MicrocodeCodeAddr(%esp), %esi\r
975f1c64
JY
278 cmpl $0x00, %esi\r
279 jnz CheckMainHeader\r
c8ec22a2 280\r
975f1c64
JY
281ParamError:\r
282 movl $0x080000002, %eax\r
9da59186 283 jmp LoadMicrocodeExit\r
c8ec22a2 284\r
975f1c64
JY
285CheckMainHeader:\r
286 #\r
c8ec22a2
JY
287 # Get processor signature and platform ID from the installed processor\r
288 # and save into registers for later use\r
289 # ebx = processor signature\r
290 # edx = platform ID\r
975f1c64
JY
291 #\r
292 movl $0x01, %eax\r
c8ec22a2
JY
293 cpuid\r
294 movl %eax, %ebx\r
975f1c64 295 movl $MSR_IA32_PLATFORM_ID, %ecx\r
c8ec22a2 296 rdmsr\r
975f1c64
JY
297 movl %edx, %ecx\r
298 shrl $0x12, %ecx #($50-$32)\r
299 andl $0x07, %ecx\r
300 movl $0x01, %edx\r
301 shll %cl,%edx\r
c8ec22a2 302\r
975f1c64 303 #\r
c8ec22a2
JY
304 # Current register usage\r
305 # esp -> stack with paramters\r
306 # esi -> microcode update to check\r
307 # ebx = processor signature\r
308 # edx = platform ID\r
975f1c64 309 #\r
c8ec22a2 310\r
975f1c64 311 #\r
c8ec22a2
JY
312 # Check for valid microcode header\r
313 # Minimal test checking for header version and loader version as 1\r
975f1c64
JY
314 #\r
315 movl $0x01, %eax\r
9da59186 316 cmpl %eax, MicrocodeHdrVersion(%esi)\r
975f1c64 317 jne AdvanceFixedSize\r
9da59186 318 cmpl %eax, MicrocodeHdrLoader(%esi)\r
975f1c64 319 jne AdvanceFixedSize\r
c8ec22a2 320\r
975f1c64 321 #\r
c8ec22a2 322 # Check if signature and plaform ID match\r
975f1c64 323 #\r
9da59186
JY
324 cmpl MicrocodeHdrProcessor(%esi), %ebx\r
325 jne LoadMicrocodeL0\r
326 testl MicrocodeHdrFlags(%esi), %edx\r
975f1c64 327 jnz LoadCheck #Jif signature and platform ID match\r
c8ec22a2 328\r
9da59186 329LoadMicrocodeL0:\r
975f1c64 330 #\r
c8ec22a2 331 # Check if extended header exists\r
9da59186 332 # First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid\r
975f1c64
JY
333 #\r
334 xorl %eax, %eax\r
9da59186 335 cmpl %eax, MicrocodeHdrTotalSize(%esi)\r
975f1c64 336 je NextMicrocode\r
9da59186 337 cmpl %eax, MicrocodeHdrDataSize(%esi)\r
975f1c64 338 je NextMicrocode\r
c8ec22a2 339\r
975f1c64 340 #\r
c8ec22a2 341 # Then verify total size - sizeof header > data size\r
975f1c64 342 #\r
9da59186
JY
343 movl MicrocodeHdrTotalSize(%esi), %ecx\r
344 subl $MicrocodeHdrLength, %ecx\r
345 cmpl MicrocodeHdrDataSize(%esi), %ecx\r
346 jle NextMicrocode\r
c8ec22a2 347\r
975f1c64 348 #\r
c8ec22a2 349 # Set edi -> extended header\r
975f1c64
JY
350 #\r
351 movl %esi, %edi\r
9da59186
JY
352 addl $MicrocodeHdrLength, %edi\r
353 addl MicrocodeHdrDataSize(%esi), %edi\r
c8ec22a2 354\r
975f1c64 355 #\r
c8ec22a2 356 # Get count of extended structures\r
975f1c64 357 #\r
9da59186 358 movl ExtSigHdrCount(%edi), %ecx\r
c8ec22a2 359\r
975f1c64 360 #\r
c8ec22a2 361 # Move pointer to first signature structure\r
975f1c64 362 #\r
9da59186 363 addl ExtSigHdrLength, %edi\r
c8ec22a2 364\r
975f1c64
JY
365CheckExtSig:\r
366 #\r
c8ec22a2 367 # Check if extended signature and platform ID match\r
975f1c64 368 #\r
9da59186
JY
369 cmpl %ebx, ExtSigProcessor(%edi)\r
370 jne LoadMicrocodeL1\r
371 test %edx, ExtSigFlags(%edi)\r
975f1c64 372 jnz LoadCheck # Jif signature and platform ID match\r
9da59186 373LoadMicrocodeL1:\r
975f1c64 374 #\r
c8ec22a2 375 # Check if any more extended signatures exist\r
975f1c64 376 #\r
9da59186 377 addl $ExtSigLength, %edi\r
975f1c64 378 loop CheckExtSig\r
c8ec22a2 379\r
975f1c64
JY
380NextMicrocode:\r
381 #\r
c8ec22a2 382 # Advance just after end of this microcode\r
975f1c64 383 #\r
c8ec22a2 384 xorl %eax, %eax\r
9da59186
JY
385 cmpl %eax, MicrocodeHdrTotalSize(%esi)\r
386 je LoadMicrocodeL2\r
387 addl MicrocodeHdrTotalSize(%esi), %esi\r
975f1c64 388 jmp CheckAddress\r
9da59186 389LoadMicrocodeL2:\r
975f1c64
JY
390 addl $0x800, %esi #add esi, dword ptr 2048\r
391 jmp CheckAddress\r
392\r
393AdvanceFixedSize:\r
394 #\r
c8ec22a2 395 # Advance by 4X dwords\r
975f1c64
JY
396 #\r
397 addl $0x400, %esi #add esi, dword ptr 1024\r
c8ec22a2 398\r
975f1c64
JY
399CheckAddress:\r
400 #\r
c8ec22a2 401 # Is valid Microcode start point ?\r
975f1c64 402 #\r
9da59186 403 cmpl $0x0ffffffff, MicrocodeHdrVersion(%esi)\r
c8ec22a2 404\r
975f1c64
JY
405 #\r
406 # Is automatic size detection ?\r
407 #\r
9da59186 408 movl MicrocodeCodeSize(%esp), %eax\r
975f1c64 409 cmpl $0x0ffffffff, %eax\r
9da59186 410 jz LoadMicrocodeL3\r
975f1c64 411 #\r
c8ec22a2 412 # Address >= microcode region address + microcode region size?\r
975f1c64 413 #\r
9da59186 414 addl MicrocodeCodeAddr(%esp), %eax\r
975f1c64 415\r
c8ec22a2 416 cmpl %eax, %esi\r
9da59186 417 jae Done #Jif address is outside of microcode region\r
975f1c64 418 jmp CheckMainHeader\r
c8ec22a2 419\r
9da59186 420LoadMicrocodeL3:\r
975f1c64
JY
421LoadCheck:\r
422 #\r
c8ec22a2 423 # Get the revision of the current microcode update loaded\r
975f1c64
JY
424 #\r
425 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
426 xorl %eax, %eax # Clear EAX\r
427 xorl %edx, %edx # Clear EDX\r
428 wrmsr # Load 0 to MSR at 8Bh\r
c8ec22a2 429\r
975f1c64 430 movl $0x01, %eax\r
c8ec22a2 431 cpuid\r
975f1c64
JY
432 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
433 rdmsr # Get current microcode signature\r
c8ec22a2 434\r
975f1c64 435 #\r
c8ec22a2 436 # Verify this microcode update is not already loaded\r
975f1c64 437 #\r
9da59186 438 cmpl %edx, MicrocodeHdrRevision(%esi)\r
975f1c64 439 je Continue\r
c8ec22a2 440\r
9da59186 441LoadMicrocode0:\r
975f1c64 442 #\r
c8ec22a2
JY
443 # EAX contains the linear address of the start of the Update Data\r
444 # EDX contains zero\r
445 # ECX contains 79h (IA32_BIOS_UPDT_TRIG)\r
446 # Start microcode load with wrmsr\r
975f1c64
JY
447 #\r
448 movl %esi, %eax\r
9da59186 449 addl $MicrocodeHdrLength, %eax\r
975f1c64
JY
450 xorl %edx, %edx\r
451 movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx\r
c8ec22a2 452 wrmsr\r
975f1c64 453 movl $0x01, %eax\r
c8ec22a2
JY
454 cpuid\r
455\r
975f1c64
JY
456Continue:\r
457 jmp NextMicrocode\r
c8ec22a2 458\r
975f1c64
JY
459Done:\r
460 movl $0x01, %eax\r
c8ec22a2 461 cpuid\r
975f1c64
JY
462 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
463 rdmsr # Get current microcode signature\r
c8ec22a2 464 xorl %eax, %eax\r
975f1c64 465 cmpl $0x00, %edx\r
9da59186 466 jnz LoadMicrocodeExit\r
975f1c64 467 movl $0x08000000E, %eax\r
c8ec22a2 468\r
9da59186 469LoadMicrocodeExit:\r
c8ec22a2
JY
470 jmp *%ebp\r
471\r
c8ec22a2 472\r
d5fb1edf
JY
473#----------------------------------------------------------------------------\r
474# EstablishStackFsp\r
475#\r
d5fb1edf
JY
476#----------------------------------------------------------------------------\r
477ASM_GLOBAL ASM_PFX(EstablishStackFsp)\r
478ASM_PFX(EstablishStackFsp):\r
479 #\r
9da59186 480 # Save parameter pointer in edx\r
d5fb1edf
JY
481 #\r
482 movl 4(%esp), %edx\r
9da59186 483\r
d5fb1edf
JY
484 #\r
485 # Enable FSP STACK\r
486 #\r
487 movl PcdGet32(PcdTemporaryRamBase), %esp\r
488 addl PcdGet32(PcdTemporaryRamSize), %esp\r
489\r
490 pushl $DATA_LEN_OF_MCUD # Size of the data region\r
491 pushl $0x4455434D # Signature of the data region 'MCUD'\r
492 pushl 12(%edx) # Code size\r
493 pushl 8(%edx) # Code base\r
d5fb1edf
JY
494 pushl 4(%edx) # Microcode size\r
495 pushl (%edx) # Microcode base\r
d5fb1edf 496\r
d5fb1edf
JY
497 #\r
498 # Save API entry/exit timestamp into stack\r
499 #\r
500 pushl $DATA_LEN_OF_PER0 # Size of the data region\r
501 pushl $0x30524550 # Signature of the data region 'PER0'\r
95c95ac0
JY
502 LOAD_EDX\r
503 pushl %edx\r
504 LOAD_EAX\r
d5fb1edf
JY
505 pushl %eax\r
506 rdtsc\r
507 pushl %edx\r
508 pushl %eax\r
509\r
510 #\r
511 # Terminator for the data on stack\r
9da59186 512 #\r
d5fb1edf
JY
513 push $0x00\r
514\r
515 #\r
9da59186 516 # Set ECX/EDX to the BootLoader temporary memory range\r
d5fb1edf
JY
517 #\r
518 movl PcdGet32 (PcdTemporaryRamBase), %ecx\r
519 movl %ecx, %edx\r
520 addl PcdGet32 (PcdTemporaryRamSize), %edx\r
521 subl PcdGet32 (PcdFspTemporaryRamSize), %edx\r
522\r
523 xorl %eax, %eax\r
9da59186 524\r
d5fb1edf
JY
525 movd %mm7, %esi #RET_ESI\r
526 jmp *%esi\r
527\r
c8ec22a2
JY
528#----------------------------------------------------------------------------\r
529# TempRamInit API\r
530#\r
531# This FSP API will load the microcode update, enable code caching for the\r
532# region specified by the boot loader and also setup a temporary stack to be\r
533# used till main memory is initialized.\r
534#\r
535#----------------------------------------------------------------------------\r
536ASM_GLOBAL ASM_PFX(TempRamInitApi)\r
537ASM_PFX(TempRamInitApi):\r
538 #\r
539 # Ensure SSE is enabled\r
540 #\r
541 ENABLE_SSE\r
542\r
543 #\r
544 # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6\r
545 #\r
546 SAVE_REGS\r
547\r
548 #\r
1c54ceb7 549 # Save timestamp into XMM6\r
c8ec22a2
JY
550 #\r
551 rdtsc\r
95c95ac0
JY
552 SAVE_EAX\r
553 SAVE_EDX\r
554\r
555 #\r
556 # Check Parameter\r
557 #\r
558 movl 4(%esp), %eax\r
559 cmpl $0x00, %eax\r
560 movl $0x80000002, %eax\r
561 jz NemInitExit\r
c8ec22a2
JY
562\r
563 #\r
564 # CPUID/DeviceID check\r
9da59186 565 # and Sec Platform Init\r
c8ec22a2 566 #\r
d5fb1edf 567 movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit\r
9da59186
JY
568 movd %esi, %mm7\r
569 .weak ASM_PFX(SecPlatformInit)\r
570 .set ASM_PFX(SecPlatformInit), ASM_PFX(SecPlatformInitDefault)\r
d5fb1edf 571 jmp ASM_PFX(SecPlatformInit)\r
975f1c64 572TempRamInitApiL1:\r
95c95ac0
JY
573 cmpl $0x00, %eax\r
574 jnz NemInitExit\r
c8ec22a2
JY
575\r
576 #\r
95c95ac0 577 # Load microcode\r
c8ec22a2 578 #\r
95c95ac0 579 LOAD_ESP\r
9da59186
JY
580 movl $TempRamInitApiL2, %esi #CALL_MMX LoadMicrocode\r
581 movd %esi, %mm7\r
582 .weak ASM_PFX(LoadMicrocode)\r
583 .set ASM_PFX(LoadMicrocode), ASM_PFX(LoadMicrocodeDefault)\r
584 jmp ASM_PFX(LoadMicrocode)\r
975f1c64 585TempRamInitApiL2:\r
9da59186
JY
586 SAVE_EAX_MICROCODE_RET_STATUS #Save microcode return status in ECX-SLOT 3 in xmm6.\r
587 #@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
588\r
589 #\r
95c95ac0 590 # Call Sec CAR Init\r
c8ec22a2 591 #\r
95c95ac0
JY
592 LOAD_ESP\r
593 movl $TempRamInitApiL3, %esi #CALL_MMX SecCarInit\r
9da59186 594 movd %esi, %mm7\r
95c95ac0 595 jmp ASM_PFX(SecCarInit)\r
d5fb1edf 596TempRamInitApiL3:\r
95c95ac0
JY
597 cmpl $0x00, %eax\r
598 jnz NemInitExit\r
c8ec22a2
JY
599\r
600 #\r
d5fb1edf 601 # EstablishStackFsp\r
c8ec22a2 602 #\r
95c95ac0 603 LOAD_ESP\r
d5fb1edf 604 movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp\r
9da59186 605 movd %esi, %mm7\r
d5fb1edf
JY
606 jmp ASM_PFX(EstablishStackFsp)\r
607TempRamInitApiL4:\r
c8ec22a2 608\r
9da59186
JY
609 LOAD_EAX_MICROCODE_RET_STATUS #Restore microcode status if no CAR init error.\r
610\r
c8ec22a2
JY
611NemInitExit:\r
612 #\r
613 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6\r
614 #\r
615 LOAD_REGS\r
616 ret\r
975f1c64 617\r
9da59186 618\r
c8ec22a2
JY
619#----------------------------------------------------------------------------\r
620# FspInit API\r
621#\r
622# This FSP API will perform the processor and chipset initialization.\r
623# This API will not return. Instead, it transfers the control to the\r
624# ContinuationFunc provided in the parameter.\r
625#\r
626#----------------------------------------------------------------------------\r
627ASM_GLOBAL ASM_PFX(FspInitApi)\r
628ASM_PFX(FspInitApi):\r
d5fb1edf
JY
629 movl $0x01, %eax\r
630 jmp FspApiCommon\r
631\r
632#----------------------------------------------------------------------------\r
633# NotifyPhase API\r
634#\r
635# This FSP API will notify the FSP about the different phases in the boot\r
636# process\r
637#\r
638#----------------------------------------------------------------------------\r
639ASM_GLOBAL ASM_PFX(NotifyPhaseApi)\r
640ASM_PFX(NotifyPhaseApi):\r
641 movl $0x02, %eax\r
642 jmp FspApiCommon\r
643\r
644#----------------------------------------------------------------------------\r
645# FspMemoryInit API\r
646#\r
647# This FSP API is called after TempRamInit and initializes the memory.\r
648#\r
649#----------------------------------------------------------------------------\r
650ASM_GLOBAL ASM_PFX(FspMemoryInitApi)\r
651ASM_PFX(FspMemoryInitApi):\r
652 movl $0x03, %eax\r
653 jmp FspApiCommon\r
654\r
655#----------------------------------------------------------------------------\r
656# TempRamExitApi API\r
657#\r
658# This API tears down temporary RAM\r
659#\r
660#----------------------------------------------------------------------------\r
661ASM_GLOBAL ASM_PFX(TempRamExitApi)\r
662ASM_PFX(TempRamExitApi):\r
663 movl $0x04, %eax\r
664 jmp FspApiCommon\r
665\r
666#----------------------------------------------------------------------------\r
667# FspSiliconInit API\r
668#\r
669# This FSP API initializes the CPU and the chipset including the IO\r
670# controllers in the chipset to enable normal operation of these devices.\r
671#\r
672#----------------------------------------------------------------------------\r
673ASM_GLOBAL ASM_PFX(FspSiliconInitApi)\r
674ASM_PFX(FspSiliconInitApi):\r
675 movl $0x05, %eax\r
676 jmp FspApiCommon\r
677\r
678#----------------------------------------------------------------------------\r
679# FspApiCommon API\r
680#\r
681# This is the FSP API common entry point to resume the FSP execution\r
682#\r
683#----------------------------------------------------------------------------\r
684ASM_GLOBAL ASM_PFX(FspApiCommon)\r
685ASM_PFX(FspApiCommon):\r
c8ec22a2 686 #\r
d5fb1edf 687 # EAX holds the API index\r
c8ec22a2 688 #\r
d5fb1edf
JY
689\r
690 #\r
691 # Stack must be ready\r
692 # \r
693 pushl %eax\r
694 addl $0x04, %esp\r
695 cmpl -4(%esp), %eax\r
696 jz FspApiCommonL0\r
c8ec22a2 697 movl $0x080000003, %eax\r
d5fb1edf 698 jmp FspApiCommonExit\r
c8ec22a2 699\r
d5fb1edf 700FspApiCommonL0:\r
c8ec22a2 701 #\r
d5fb1edf 702 # Verify the calling condition\r
c8ec22a2 703 #\r
d5fb1edf
JY
704 pushal\r
705 pushl %eax\r
c8ec22a2 706 call ASM_PFX(FspApiCallingCheck)\r
975f1c64 707 addl $0x04, %esp\r
975f1c64 708 cmpl $0x00, %eax\r
d5fb1edf
JY
709 jz FspApiCommonL1\r
710 movl %eax, 0x1C(%esp) # mov dword ptr [esp + 4 * 7], eax\r
711 popal\r
712 ret\r
713\r
714FspApiCommonL1:\r
715 popal\r
716 cmpl $0x01, %eax # FspInit API\r
717 jz FspApiCommonL2\r
718 cmpl $0x03, %eax # FspMemoryInit API\r
719 jz FspApiCommonL2\r
720 jmp Pei2LoaderSwitchStack\r
c8ec22a2 721\r
d5fb1edf
JY
722FspApiCommonL2:\r
723 #\r
724 # FspInit and FspMemoryInit APIs, setup the initial stack frame\r
725 # \r
726 \r
c8ec22a2
JY
727 #\r
728 # Store the address in FSP which will return control to the BL\r
729 #\r
d5fb1edf 730 pushl $FspApiCommonExit\r
c8ec22a2
JY
731\r
732 #\r
733 # Create a Task Frame in the stack for the Boot Loader\r
734 #\r
d5fb1edf 735 pushfl # 2 pushf for 4 byte alignment\r
c8ec22a2
JY
736 cli\r
737 pushal\r
738\r
975f1c64 739 #\r
c8ec22a2 740 # Reserve 8 bytes for IDT save/restore\r
975f1c64
JY
741 #\r
742 subl $0x08, %esp\r
743 sidt (%esp)\r
c8ec22a2
JY
744\r
745 #\r
746 # Setup new FSP stack\r
747 #\r
d5fb1edf
JY
748 movl %esp, %edi\r
749 movl PcdGet32(PcdTemporaryRamBase), %esp\r
750 addl PcdGet32(PcdTemporaryRamSize), %esp\r
975f1c64 751 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp\r
c8ec22a2 752\r
c8ec22a2 753 #\r
d5fb1edf
JY
754 # Pass the API Idx to SecStartup\r
755 #\r
756 pushl %eax\r
757 \r
758 #\r
9da59186 759 # Pass the BootLoader stack to SecStartup\r
d5fb1edf
JY
760 #\r
761 pushl %edi\r
c8ec22a2
JY
762\r
763 #\r
764 # Pass entry point of the PEI core\r
765 #\r
d5fb1edf
JY
766 call ASM_PFX(GetFspBaseAddress)\r
767 movl %eax, %edi\r
768 addl PcdGet32(PcdFspAreaSize), %edi\r
769 subl $0x20, %edi\r
770 addl %ds:(%edi), %eax\r
771 pushl %eax\r
c8ec22a2
JY
772\r
773 #\r
774 # Pass BFV into the PEI Core\r
775 # It uses relative address to calucate the actual boot FV base\r
776 # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and\r
777 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,\r
778 # they are different. The code below can handle both cases.\r
779 #\r
d5fb1edf
JY
780 call ASM_PFX(GetFspBaseAddress)\r
781 movl %eax, %edi\r
782 call ASM_PFX(GetBootFirmwareVolumeOffset)\r
783 addl %edi, %eax\r
784 pushl %eax\r
c8ec22a2
JY
785\r
786 #\r
787 # Pass stack base and size into the PEI Core\r
788 #\r
d5fb1edf
JY
789 movl PcdGet32(PcdTemporaryRamBase), %eax\r
790 addl PcdGet32(PcdTemporaryRamSize), %eax\r
791 subl PcdGet32(PcdFspTemporaryRamSize), %eax\r
792 pushl %eax\r
793 pushl PcdGet32(PcdFspTemporaryRamSize)\r
c8ec22a2
JY
794\r
795 #\r
796 # Pass Control into the PEI Core\r
797 #\r
798 call ASM_PFX(SecStartup)\r
799\r
d5fb1edf 800FspApiCommonExit:\r
c8ec22a2
JY
801 ret\r
802\r