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