]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
DHCP6 bug fix:
[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
208# PlatformBasicInitDflt\r
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
JY
216#------------------------------------------------------------------------------\r
217ASM_GLOBAL ASM_PFX(PlatformBasicInitDflt)\r
218ASM_PFX(PlatformBasicInitDflt):\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
JY
224\r
225PlatformBasicInitDfltExit:\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
d5fb1edf
JY
247 movd %xmm7, %ebp\r
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
454# Following is the code copied from BYTFSP, need to figure out what it is doing..\r
455#\r
456#----------------------------------------------------------------------------\r
457ASM_GLOBAL ASM_PFX(EstablishStackFsp)\r
458ASM_PFX(EstablishStackFsp):\r
459 #\r
460 # Save parameter pointer in edx \r
461 #\r
462 movl 4(%esp), %edx\r
463 \r
464 #\r
465 # Enable FSP STACK\r
466 #\r
467 movl PcdGet32(PcdTemporaryRamBase), %esp\r
468 addl PcdGet32(PcdTemporaryRamSize), %esp\r
469\r
470 pushl $DATA_LEN_OF_MCUD # Size of the data region\r
471 pushl $0x4455434D # Signature of the data region 'MCUD'\r
472 pushl 12(%edx) # Code size\r
473 pushl 8(%edx) # Code base\r
474 cmpl $0, %edx # Is parameter pointer valid ?\r
475 jz InvalidMicrocodeRegion\r
476 pushl 4(%edx) # Microcode size\r
477 pushl (%edx) # Microcode base\r
478 jmp EstablishStackFspExit\r
479\r
480InvalidMicrocodeRegion:\r
481 push $0 # Microcode size\r
482 push $0 # Microcode base\r
483 \r
484EstablishStackFspExit:\r
485 #\r
486 # Save API entry/exit timestamp into stack\r
487 #\r
488 pushl $DATA_LEN_OF_PER0 # Size of the data region\r
489 pushl $0x30524550 # Signature of the data region 'PER0'\r
490 movd %xmm4, %eax\r
491 pushl %eax\r
492 movd %xmm5, %eax\r
493 pushl %eax\r
494 rdtsc\r
495 pushl %edx\r
496 pushl %eax\r
497\r
498 #\r
499 # Terminator for the data on stack\r
500 # \r
501 push $0x00\r
502\r
503 #\r
504 # Set ECX/EDX to the bootloader temporary memory range\r
505 #\r
506 movl PcdGet32 (PcdTemporaryRamBase), %ecx\r
507 movl %ecx, %edx\r
508 addl PcdGet32 (PcdTemporaryRamSize), %edx\r
509 subl PcdGet32 (PcdFspTemporaryRamSize), %edx\r
510\r
511 xorl %eax, %eax\r
512 \r
513 movd %mm7, %esi #RET_ESI\r
514 jmp *%esi\r
515\r
c8ec22a2
JY
516#----------------------------------------------------------------------------\r
517# TempRamInit API\r
518#\r
519# This FSP API will load the microcode update, enable code caching for the\r
520# region specified by the boot loader and also setup a temporary stack to be\r
521# used till main memory is initialized.\r
522#\r
523#----------------------------------------------------------------------------\r
524ASM_GLOBAL ASM_PFX(TempRamInitApi)\r
525ASM_PFX(TempRamInitApi):\r
526 #\r
527 # Ensure SSE is enabled\r
528 #\r
529 ENABLE_SSE\r
530\r
531 #\r
532 # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6\r
533 #\r
534 SAVE_REGS\r
535\r
536 #\r
537 # Save timestamp into XMM4 & XMM5\r
538 #\r
539 rdtsc\r
d5fb1edf
JY
540 movd %edx, %xmm4\r
541 movd %eax, %xmm5\r
c8ec22a2
JY
542\r
543 #\r
544 # CPUID/DeviceID check\r
545 #\r
975f1c64 546 movl $TempRamInitApiL0, %eax\r
d5fb1edf 547 jmp ASM_PFX(FspSelfCheckDflt) # @note: ESP can not be changed.\r
975f1c64
JY
548TempRamInitApiL0:\r
549 cmpl $0x00, %eax\r
550 jnz NemInitExit\r
c8ec22a2
JY
551\r
552 #\r
d5fb1edf 553 # Sec Platform Init\r
c8ec22a2 554 #\r
d5fb1edf
JY
555 movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit\r
556 movd %mm7, %esi\r
557 jmp ASM_PFX(SecPlatformInit)\r
975f1c64 558TempRamInitApiL1:\r
c8ec22a2
JY
559\r
560 #\r
d5fb1edf 561 # Call Sec CAR Init\r
c8ec22a2 562 #\r
d5fb1edf
JY
563 movl $TempRamInitApiL2, %esi #CALL_MMX SecCarInit\r
564 movd %mm7, %esi\r
565 jmp ASM_PFX(SecCarInit)\r
975f1c64 566TempRamInitApiL2:\r
c8ec22a2 567\r
d5fb1edf 568 # @todo: ESP has been modified, we need to restore here.\r
c8ec22a2 569\r
d5fb1edf
JY
570 LOAD_REGS\r
571 SAVE_REGS\r
c8ec22a2
JY
572\r
573 #\r
d5fb1edf 574 # Load microcode\r
c8ec22a2 575 #\r
d5fb1edf
JY
576 movl $TempRamInitApiL3, %esi #CALL_MMX LoadUcode\r
577 movd %mm7, %esi\r
578 jmp ASM_PFX(LoadUcode)\r
579TempRamInitApiL3:\r
c8ec22a2
JY
580\r
581 #\r
d5fb1edf 582 # EstablishStackFsp\r
c8ec22a2 583 #\r
d5fb1edf
JY
584 movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp\r
585 movd %mm7, %esi\r
586 jmp ASM_PFX(EstablishStackFsp)\r
587TempRamInitApiL4:\r
c8ec22a2
JY
588\r
589NemInitExit:\r
590 #\r
591 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6\r
592 #\r
593 LOAD_REGS\r
594 ret\r
975f1c64 595\r
c8ec22a2
JY
596#----------------------------------------------------------------------------\r
597# FspInit API\r
598#\r
599# This FSP API will perform the processor and chipset initialization.\r
600# This API will not return. Instead, it transfers the control to the\r
601# ContinuationFunc provided in the parameter.\r
602#\r
603#----------------------------------------------------------------------------\r
604ASM_GLOBAL ASM_PFX(FspInitApi)\r
605ASM_PFX(FspInitApi):\r
d5fb1edf
JY
606 movl $0x01, %eax\r
607 jmp FspApiCommon\r
608\r
609#----------------------------------------------------------------------------\r
610# NotifyPhase API\r
611#\r
612# This FSP API will notify the FSP about the different phases in the boot\r
613# process\r
614#\r
615#----------------------------------------------------------------------------\r
616ASM_GLOBAL ASM_PFX(NotifyPhaseApi)\r
617ASM_PFX(NotifyPhaseApi):\r
618 movl $0x02, %eax\r
619 jmp FspApiCommon\r
620\r
621#----------------------------------------------------------------------------\r
622# FspMemoryInit API\r
623#\r
624# This FSP API is called after TempRamInit and initializes the memory.\r
625#\r
626#----------------------------------------------------------------------------\r
627ASM_GLOBAL ASM_PFX(FspMemoryInitApi)\r
628ASM_PFX(FspMemoryInitApi):\r
629 movl $0x03, %eax\r
630 jmp FspApiCommon\r
631\r
632#----------------------------------------------------------------------------\r
633# TempRamExitApi API\r
634#\r
635# This API tears down temporary RAM\r
636#\r
637#----------------------------------------------------------------------------\r
638ASM_GLOBAL ASM_PFX(TempRamExitApi)\r
639ASM_PFX(TempRamExitApi):\r
640 movl $0x04, %eax\r
641 jmp FspApiCommon\r
642\r
643#----------------------------------------------------------------------------\r
644# FspSiliconInit API\r
645#\r
646# This FSP API initializes the CPU and the chipset including the IO\r
647# controllers in the chipset to enable normal operation of these devices.\r
648#\r
649#----------------------------------------------------------------------------\r
650ASM_GLOBAL ASM_PFX(FspSiliconInitApi)\r
651ASM_PFX(FspSiliconInitApi):\r
652 movl $0x05, %eax\r
653 jmp FspApiCommon\r
654\r
655#----------------------------------------------------------------------------\r
656# FspApiCommon API\r
657#\r
658# This is the FSP API common entry point to resume the FSP execution\r
659#\r
660#----------------------------------------------------------------------------\r
661ASM_GLOBAL ASM_PFX(FspApiCommon)\r
662ASM_PFX(FspApiCommon):\r
c8ec22a2 663 #\r
d5fb1edf 664 # EAX holds the API index\r
c8ec22a2 665 #\r
d5fb1edf
JY
666\r
667 #\r
668 # Stack must be ready\r
669 # \r
670 pushl %eax\r
671 addl $0x04, %esp\r
672 cmpl -4(%esp), %eax\r
673 jz FspApiCommonL0\r
c8ec22a2 674 movl $0x080000003, %eax\r
d5fb1edf 675 jmp FspApiCommonExit\r
c8ec22a2 676\r
d5fb1edf 677FspApiCommonL0:\r
c8ec22a2 678 #\r
d5fb1edf 679 # Verify the calling condition\r
c8ec22a2 680 #\r
d5fb1edf
JY
681 pushal\r
682 pushl %eax\r
c8ec22a2 683 call ASM_PFX(FspApiCallingCheck)\r
975f1c64 684 addl $0x04, %esp\r
975f1c64 685 cmpl $0x00, %eax\r
d5fb1edf
JY
686 jz FspApiCommonL1\r
687 movl %eax, 0x1C(%esp) # mov dword ptr [esp + 4 * 7], eax\r
688 popal\r
689 ret\r
690\r
691FspApiCommonL1:\r
692 popal\r
693 cmpl $0x01, %eax # FspInit API\r
694 jz FspApiCommonL2\r
695 cmpl $0x03, %eax # FspMemoryInit API\r
696 jz FspApiCommonL2\r
697 jmp Pei2LoaderSwitchStack\r
c8ec22a2 698\r
d5fb1edf
JY
699FspApiCommonL2:\r
700 #\r
701 # FspInit and FspMemoryInit APIs, setup the initial stack frame\r
702 # \r
703 \r
c8ec22a2
JY
704 #\r
705 # Store the address in FSP which will return control to the BL\r
706 #\r
d5fb1edf 707 pushl $FspApiCommonExit\r
c8ec22a2
JY
708\r
709 #\r
710 # Create a Task Frame in the stack for the Boot Loader\r
711 #\r
d5fb1edf 712 pushfl # 2 pushf for 4 byte alignment\r
c8ec22a2
JY
713 cli\r
714 pushal\r
715\r
975f1c64 716 #\r
c8ec22a2 717 # Reserve 8 bytes for IDT save/restore\r
975f1c64
JY
718 #\r
719 subl $0x08, %esp\r
720 sidt (%esp)\r
c8ec22a2
JY
721\r
722 #\r
723 # Setup new FSP stack\r
724 #\r
d5fb1edf
JY
725 movl %esp, %edi\r
726 movl PcdGet32(PcdTemporaryRamBase), %esp\r
727 addl PcdGet32(PcdTemporaryRamSize), %esp\r
975f1c64 728 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp\r
c8ec22a2 729\r
c8ec22a2 730 #\r
d5fb1edf
JY
731 # Pass the API Idx to SecStartup\r
732 #\r
733 pushl %eax\r
734 \r
735 #\r
736 # Pass the bootloader stack to SecStartup\r
737 #\r
738 pushl %edi\r
c8ec22a2
JY
739\r
740 #\r
741 # Pass entry point of the PEI core\r
742 #\r
d5fb1edf
JY
743 call ASM_PFX(GetFspBaseAddress)\r
744 movl %eax, %edi\r
745 addl PcdGet32(PcdFspAreaSize), %edi\r
746 subl $0x20, %edi\r
747 addl %ds:(%edi), %eax\r
748 pushl %eax\r
c8ec22a2
JY
749\r
750 #\r
751 # Pass BFV into the PEI Core\r
752 # It uses relative address to calucate the actual boot FV base\r
753 # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and\r
754 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,\r
755 # they are different. The code below can handle both cases.\r
756 #\r
d5fb1edf
JY
757 call ASM_PFX(GetFspBaseAddress)\r
758 movl %eax, %edi\r
759 call ASM_PFX(GetBootFirmwareVolumeOffset)\r
760 addl %edi, %eax\r
761 pushl %eax\r
c8ec22a2
JY
762\r
763 #\r
764 # Pass stack base and size into the PEI Core\r
765 #\r
d5fb1edf
JY
766 movl PcdGet32(PcdTemporaryRamBase), %eax\r
767 addl PcdGet32(PcdTemporaryRamSize), %eax\r
768 subl PcdGet32(PcdFspTemporaryRamSize), %eax\r
769 pushl %eax\r
770 pushl PcdGet32(PcdFspTemporaryRamSize)\r
c8ec22a2
JY
771\r
772 #\r
773 # Pass Control into the PEI Core\r
774 #\r
775 call ASM_PFX(SecStartup)\r
776\r
d5fb1edf 777FspApiCommonExit:\r
c8ec22a2
JY
778 ret\r
779\r
c8ec22a2 780\r