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