]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
MdeModulePkg: Update library class name of PlatformHookLibSerialPortPpi.inf
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.s
... / ...
CommitLineData
1#------------------------------------------------------------------------------\r
2#\r
3# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
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
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
71\r
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
77#\r
78 pinsrw $0x02, %ebx, %xmm7\r
79 ror $0x10, %ebx\r
80 pinsrw $0x03, %ebx, %xmm7\r
81 ror $0x10, %ebx\r
82#\r
83 pinsrw $0x04, %esi, %xmm7\r
84 ror $0x10, %esi\r
85 pinsrw $0x05, %esi, %xmm7\r
86 ror $0x10, %esi\r
87#\r
88 pinsrw $0x06, %edi, %xmm7\r
89 ror $0x10, %edi\r
90 pinsrw $0x07, %edi, %xmm7\r
91 ror $0x10, %edi\r
92#\r
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
98\r
99.macro LOAD_REGS\r
100 pshufd $0xe4, %xmm7, %xmm7\r
101 movd %xmm7, %ebp \r
102 pshufd $0xe4, %xmm7, %xmm7\r
103#\r
104 pshufd $0x39, %xmm7, %xmm7\r
105 movd %xmm7, %ebx\r
106 pshufd $0x93, %xmm7, %xmm7\r
107#\r
108 pshufd $0x4e, %xmm7, %xmm7\r
109 movd %xmm7, %esi\r
110 pshufd $0x4e, %xmm7, %xmm7\r
111#\r
112 pshufd $0x93, %xmm7, %xmm7\r
113 movd %xmm7, %edi\r
114 pshufd $0x39, %xmm7, %xmm7\r
115#\r
116 movd %xmm6, %esp\r
117.endm\r
118\r
119.macro LOAD_EAX\r
120 pshufd $0x39, %xmm6, %xmm6\r
121 movd %xmm6, %eax\r
122 pshufd $0x93, %xmm6, %xmm6\r
123.endm\r
124\r
125.macro LOAD_EDX\r
126 pshufd $0xe4, %xmm6, %xmm6\r
127 movd %xmm6, %edx\r
128 pshufd $0xe4, %xmm6, %xmm6\r
129.endm\r
130\r
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
143.endm\r
144\r
145.macro LOAD_ESP\r
146 movd %xmm6, %esp\r
147.endm\r
148\r
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
168ASM_GLOBAL ASM_PFX(FspImageSizeOffset)\r
169ASM_GLOBAL ASM_PFX(SecStartup)\r
170ASM_GLOBAL ASM_PFX(FspApiCallingCheck)\r
171\r
172#\r
173# Following functions will be provided in PlatformSecLib\r
174#\r
175ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)\r
176ASM_GLOBAL ASM_PFX(Pei2LoaderSwitchStack)\r
177\r
178\r
179#\r
180# Define the data length that we saved on the stack top\r
181#\r
182.equ DATA_LEN_OF_PER0, 0x018\r
183.equ DATA_LEN_OF_MCUD, 0x018\r
184.equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)\r
185\r
186#------------------------------------------------------------------------------\r
187# FspSelfCheckDflt\r
188# Inputs:\r
189# eax -> Return address\r
190# Outputs:\r
191# eax -> 0 - Successful, Non-zero - Failed.\r
192# Register Usage:\r
193# eax is cleared and ebp is used for return address.\r
194# All others reserved.\r
195#------------------------------------------------------------------------------\r
196ASM_GLOBAL ASM_PFX(FspSelfCheckDflt)\r
197ASM_PFX(FspSelfCheckDflt):\r
198 #\r
199 # Save return address to EBP\r
200 #\r
201 movl %eax, %ebp\r
202 xorl %eax, %eax\r
203\r
204FspSelfCheckDfltExit:\r
205 jmp *%ebp\r
206\r
207\r
208#------------------------------------------------------------------------------\r
209# PlatformBasicInitDflt\r
210# Inputs:\r
211# eax -> Return address\r
212# Outputs:\r
213# eax -> 0 - Successful, Non-zero - Failed.\r
214# Register Usage:\r
215# eax is cleared and ebp is used for return address.\r
216# All others reserved.\r
217#------------------------------------------------------------------------------\r
218ASM_GLOBAL ASM_PFX(PlatformBasicInitDflt)\r
219ASM_PFX(PlatformBasicInitDflt):\r
220 #\r
221 # Save return address to EBP\r
222 #\r
223 movl %eax, %ebp\r
224 xorl %eax, %eax\r
225\r
226PlatformBasicInitDfltExit:\r
227 jmp *%ebp\r
228\r
229\r
230#------------------------------------------------------------------------------\r
231# LoadUcode\r
232#\r
233# Inputs:\r
234# esp -> LOAD_UCODE_PARAMS pointer\r
235# Register Usage:\r
236# esp Preserved\r
237# All others destroyed\r
238# Assumptions:\r
239# No memory available, stack is hard-coded and used for return address\r
240# Executed by SBSP and NBSP\r
241# Beginning of microcode update region starts on paragraph boundary\r
242#------------------------------------------------------------------------------\r
243ASM_GLOBAL ASM_PFX(LoadUcode)\r
244ASM_PFX(LoadUcode): \r
245 #\r
246 # Save return address to EBP\r
247 #\r
248 movl %eax, %ebp\r
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
254 movl %eax, %esp\r
255 movl LoadUcodeParamsUcodeCodeAddr(%esp), %esi #mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr\r
256 cmpl $0x00, %esi\r
257 jnz CheckMainHeader\r
258\r
259ParamError:\r
260 movl $0x080000002, %eax\r
261 jmp LoadUcodeExit\r
262\r
263CheckMainHeader:\r
264 #\r
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
269 #\r
270 movl $0x01, %eax\r
271 cpuid\r
272 movl %eax, %ebx\r
273 movl $MSR_IA32_PLATFORM_ID, %ecx\r
274 rdmsr\r
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
280\r
281 #\r
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
287 #\r
288\r
289 #\r
290 # Check for valid microcode header\r
291 # Minimal test checking for header version and loader version as 1\r
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
298\r
299 #\r
300 # Check if signature and plaform ID match\r
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
306\r
307LoadUcodeL0:\r
308 #\r
309 # Check if extended header exists\r
310 # First check if total_size and data_size are valid\r
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
317\r
318 #\r
319 # Then verify total size - sizeof header > data size\r
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
325\r
326 #\r
327 # Set edi -> extended header\r
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
332\r
333 #\r
334 # Get count of extended structures\r
335 #\r
336 movl ExtSigHdrCount(%edi), %ecx #mov ecx, [edi].ext_sig_hdr.count\r
337\r
338 #\r
339 # Move pointer to first signature structure\r
340 #\r
341 addl ExtSigHdrLength, %edi #add edi, sizeof ext_sig_hdr\r
342\r
343CheckExtSig:\r
344 #\r
345 # Check if extended signature and platform ID match\r
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
353 # Check if any more extended signatures exist\r
354 #\r
355 addl $ExtSigLength, %edi #add edi, sizeof ext_sig\r
356 loop CheckExtSig\r
357\r
358NextMicrocode:\r
359 #\r
360 # Advance just after end of this microcode\r
361 #\r
362 xorl %eax, %eax\r
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
373 # Advance by 4X dwords\r
374 #\r
375 addl $0x400, %esi #add esi, dword ptr 1024\r
376\r
377CheckAddress:\r
378 #\r
379 # Is valid Microcode start point ?\r
380 #\r
381 cmpl $0x0ffffffff, UcodeHdrVersion(%esi)\r
382\r
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
390 # Address >= microcode region address + microcode region size?\r
391 #\r
392 addl LoadUcodeParamsUcodeCodeAddr(%esp), %eax #mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr\r
393\r
394 cmpl %eax, %esi\r
395 jae Done #Jif address is outside of ucode region\r
396 jmp CheckMainHeader\r
397\r
398LoadUcodeL3:\r
399LoadCheck:\r
400 #\r
401 # Get the revision of the current microcode update loaded\r
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
407\r
408 movl $0x01, %eax\r
409 cpuid\r
410 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
411 rdmsr # Get current microcode signature\r
412\r
413 #\r
414 # Verify this microcode update is not already loaded\r
415 #\r
416 cmpl %edx, UcodeHdrRevision(%esi) #cmp [esi].ucode_hdr.revision, edx\r
417 je Continue\r
418\r
419LoadMicrocode:\r
420 #\r
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
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
430 wrmsr\r
431 movl $0x01, %eax\r
432 cpuid\r
433\r
434Continue:\r
435 jmp NextMicrocode\r
436\r
437Done:\r
438 movl $0x01, %eax\r
439 cpuid\r
440 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
441 rdmsr # Get current microcode signature\r
442 xorl %eax, %eax\r
443 cmpl $0x00, %edx\r
444 jnz LoadUcodeExit\r
445 movl $0x08000000E, %eax\r
446\r
447LoadUcodeExit:\r
448 jmp *%ebp\r
449\r
450\r
451#----------------------------------------------------------------------------\r
452# TempRamInit API\r
453#\r
454# This FSP API will load the microcode update, enable code caching for the\r
455# region specified by the boot loader and also setup a temporary stack to be\r
456# used till main memory is initialized.\r
457#\r
458#----------------------------------------------------------------------------\r
459ASM_GLOBAL ASM_PFX(TempRamInitApi)\r
460ASM_PFX(TempRamInitApi):\r
461 #\r
462 # Ensure SSE is enabled\r
463 #\r
464 ENABLE_SSE\r
465\r
466 #\r
467 # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6\r
468 #\r
469 SAVE_REGS\r
470\r
471 #\r
472 # Save timestamp into XMM4 & XMM5\r
473 #\r
474 rdtsc\r
475 SAVE_EAX\r
476 SAVE_EDX\r
477\r
478 #\r
479 # Check Parameter\r
480 #\r
481 movl 4(%esp), %eax\r
482 cmpl $0x00, %eax\r
483 movl $0x80000002, %eax\r
484 jz NemInitExit\r
485\r
486 #\r
487 # CPUID/DeviceID check\r
488 #\r
489 movl $TempRamInitApiL0, %eax\r
490 jmp ASM_PFX(FspSelfCheckDflt) # Note: ESP can not be changed.\r
491TempRamInitApiL0:\r
492 cmpl $0x00, %eax\r
493 jnz NemInitExit\r
494\r
495 #\r
496 # Platform Basic Init.\r
497 #\r
498 movl $TempRamInitApiL1, %eax\r
499 jmp ASM_PFX(PlatformBasicInitDflt)\r
500TempRamInitApiL1:\r
501 cmpl $0x00, %eax\r
502 jnz NemInitExit\r
503\r
504 #\r
505 # Load microcode\r
506 #\r
507 movl $TempRamInitApiL2, %eax\r
508 addl $0x04, %esp\r
509 jmp LoadUcode\r
510\r
511TempRamInitApiL2:\r
512 LOAD_ESP\r
513 cmpl $0x00, %eax\r
514 jnz NemInitExit\r
515\r
516 #\r
517 # Call platform NEM init\r
518 #\r
519 movl $TempRamInitApiL3, %eax\r
520 addl $0x04, %esp\r
521 jmp ASM_PFX(PlatformTempRamInit)\r
522TempRamInitApiL3:\r
523 subl $0x04, %esp\r
524 cmpl $0x00, %eax\r
525 jnz NemInitExit\r
526\r
527 #\r
528 # Save parameter pointer in edx\r
529 #\r
530 movl 4(%esp), %edx\r
531\r
532 #\r
533 # Enable FSP STACK\r
534 #\r
535 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp\r
536 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %esp\r
537\r
538 pushl $DATA_LEN_OF_MCUD # Size of the data region\r
539 pushl $0x4455434D # Signature of the data region 'MCUD'\r
540 pushl 4(%edx) # Microcode size\r
541 pushl (%edx) # Microcode base\r
542 pushl 12(%edx) # Code size\r
543 pushl 8(%edx) # Code base\r
544\r
545 #\r
546 # Save API entry/exit timestamp into stack\r
547 #\r
548 pushl $DATA_LEN_OF_PER0 # Size of the data region\r
549 pushl $0x30524550 # Signature of the data region 'PER0'\r
550 rdtsc\r
551 pushl %edx\r
552 pushl %eax\r
553 LOAD_EAX\r
554 LOAD_EDX\r
555 pushl %edx\r
556 pushl %eax\r
557\r
558 #\r
559 # Terminator for the data on stack\r
560 #\r
561 pushl $0x00\r
562\r
563 #\r
564 # Set ECX/EDX to the bootloader temporary memory range\r
565 #\r
566 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %ecx\r
567 movl %ecx, %edx\r
568 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %edx\r
569 subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %edx\r
570\r
571 xorl %eax, %eax\r
572\r
573NemInitExit:\r
574 #\r
575 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6\r
576 #\r
577 LOAD_REGS\r
578 ret\r
579\r
580\r
581#----------------------------------------------------------------------------\r
582# FspInit API\r
583#\r
584# This FSP API will perform the processor and chipset initialization.\r
585# This API will not return. Instead, it transfers the control to the\r
586# ContinuationFunc provided in the parameter.\r
587#\r
588#----------------------------------------------------------------------------\r
589ASM_GLOBAL ASM_PFX(FspInitApi)\r
590ASM_PFX(FspInitApi):\r
591 #\r
592 # Stack must be ready\r
593 #\r
594 pushl $0x087654321\r
595 popl %eax\r
596 cmpl $0x087654321, %eax\r
597 jz FspInitApiL0\r
598 movl $0x080000003, %eax\r
599 jmp FspInitApiexit\r
600\r
601FspInitApiL0:\r
602 #\r
603 # Additional check\r
604 #\r
605 pusha\r
606 pushl $0x01\r
607 call ASM_PFX(FspApiCallingCheck)\r
608 addl $0x04, %esp\r
609 movl %eax, 28(%esp)\r
610 popa\r
611 cmpl $0x00, %eax\r
612 jz FspInitApiL1\r
613 jmp FspInitApiexit\r
614\r
615FspInitApiL1:\r
616 #\r
617 # Store the address in FSP which will return control to the BL\r
618 #\r
619 pushl $FspInitApiexit\r
620\r
621 #\r
622 # Create a Task Frame in the stack for the Boot Loader\r
623 #\r
624 pushfl # 2 pushf for 4 byte alignment\r
625 cli\r
626 pushal\r
627\r
628 #\r
629 # Reserve 8 bytes for IDT save/restore\r
630 #\r
631 subl $0x08, %esp\r
632 sidt (%esp)\r
633\r
634 #\r
635 # Setup new FSP stack\r
636 #\r
637 movl %esp, %eax\r
638 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp\r
639 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %esp\r
640 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp\r
641\r
642 # Save the bootloader's stack pointer\r
643 #\r
644 pushl %eax\r
645\r
646 #\r
647 # Pass entry point of the PEI core\r
648 #\r
649 call ASM_PFX(GetFspBaseAddress)\r
650 movl ASM_PFX(FspImageSizeOffset), %edi\r
651 movl (%eax, %edi), %edi\r
652 addl %eax, %edi\r
653 subl $0x20, %edi\r
654 addl (%edi), %eax\r
655 pushl %eax\r
656\r
657 #\r
658 # Pass BFV into the PEI Core\r
659 # It uses relative address to calucate the actual boot FV base\r
660 # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and\r
661 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,\r
662 # they are different. The code below can handle both cases.\r
663 #\r
664 call ASM_PFX(GetFspBaseAddress)\r
665 movl %eax , %edi\r
666 call ASM_PFX(GetBootFirmwareVolumeOffset)\r
667 addl %edi ,%eax\r
668 pushl %eax\r
669\r
670 #\r
671 # Pass stack base and size into the PEI Core\r
672 #\r
673 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %eax\r
674 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %eax\r
675 subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %eax\r
676 pushl %eax\r
677 pushl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)\r
678\r
679 #\r
680 # Pass Control into the PEI Core\r
681 #\r
682 call ASM_PFX(SecStartup)\r
683\r
684FspInitApiexit:\r
685 ret\r
686\r
687\r
688#----------------------------------------------------------------------------\r
689# NotifyPhase API\r
690#\r
691# This FSP API will notify the FSP about the different phases in the boot\r
692# process\r
693#\r
694#----------------------------------------------------------------------------\r
695ASM_GLOBAL ASM_PFX(NotifyPhaseApi)\r
696ASM_PFX(NotifyPhaseApi):\r
697 #\r
698 # Stack must be ready\r
699 #\r
700 pushl $0x0087654321\r
701 popl %eax\r
702 cmpl $0x087654321, %eax\r
703 jz NotifyPhaseApiL0\r
704 movl $0x080000003, %eax\r
705 jmp NotifyPhaseApiErrExit\r
706\r
707NotifyPhaseApiL0:\r
708 #\r
709 # Verify the calling condition\r
710 #\r
711 pusha\r
712 pushl $0x02\r
713 call ASM_PFX(FspApiCallingCheck)\r
714 addl $0x04, %esp\r
715 movl %eax, 28(%esp)\r
716 popa\r
717\r
718 cmpl $0x00, %eax\r
719 jz NotifyPhaseApiL1\r
720\r
721 #\r
722 # Error return\r
723 #\r
724NotifyPhaseApiErrExit:\r
725 ret\r
726\r
727NotifyPhaseApiL1:\r
728 jmp ASM_PFX(Pei2LoaderSwitchStack)\r
729\r
730\r
731\r
732#END\r