]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
Update IntelFspPkg according to FSP1.1.
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.s
... / ...
CommitLineData
1#------------------------------------------------------------------------------\r
2#\r
3# Copyright (c) 2014 - 2015, 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(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
194#------------------------------------------------------------------------------\r
195ASM_GLOBAL ASM_PFX(FspSelfCheckDflt)\r
196ASM_PFX(FspSelfCheckDflt):\r
197 #\r
198 # Save return address to EBP\r
199 #\r
200 movl %eax, %ebp\r
201 xorl %eax, %eax\r
202\r
203FspSelfCheckDfltExit:\r
204 jmp *%ebp\r
205\r
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
216#------------------------------------------------------------------------------\r
217ASM_GLOBAL ASM_PFX(PlatformBasicInitDflt)\r
218ASM_PFX(PlatformBasicInitDflt):\r
219 #\r
220 # Save return address to EBP\r
221 #\r
222 movl %eax, %ebp\r
223 xorl %eax, %eax\r
224\r
225PlatformBasicInitDfltExit:\r
226 jmp *%ebp\r
227\r
228\r
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
241#------------------------------------------------------------------------------\r
242ASM_GLOBAL ASM_PFX(LoadUcode)\r
243ASM_PFX(LoadUcode): \r
244 #\r
245 # Save return address to EBP\r
246 #\r
247 movd %xmm7, %ebp\r
248\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# 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
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
540 movd %edx, %xmm4\r
541 movd %eax, %xmm5\r
542\r
543 #\r
544 # CPUID/DeviceID check\r
545 #\r
546 movl $TempRamInitApiL0, %eax\r
547 jmp ASM_PFX(FspSelfCheckDflt) # @note: ESP can not be changed.\r
548TempRamInitApiL0:\r
549 cmpl $0x00, %eax\r
550 jnz NemInitExit\r
551\r
552 #\r
553 # Sec Platform Init\r
554 #\r
555 movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit\r
556 movd %mm7, %esi\r
557 jmp ASM_PFX(SecPlatformInit)\r
558TempRamInitApiL1:\r
559\r
560 #\r
561 # Call Sec CAR Init\r
562 #\r
563 movl $TempRamInitApiL2, %esi #CALL_MMX SecCarInit\r
564 movd %mm7, %esi\r
565 jmp ASM_PFX(SecCarInit)\r
566TempRamInitApiL2:\r
567\r
568 # @todo: ESP has been modified, we need to restore here.\r
569\r
570 LOAD_REGS\r
571 SAVE_REGS\r
572\r
573 #\r
574 # Load microcode\r
575 #\r
576 movl $TempRamInitApiL3, %esi #CALL_MMX LoadUcode\r
577 movd %mm7, %esi\r
578 jmp ASM_PFX(LoadUcode)\r
579TempRamInitApiL3:\r
580\r
581 #\r
582 # EstablishStackFsp\r
583 #\r
584 movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp\r
585 movd %mm7, %esi\r
586 jmp ASM_PFX(EstablishStackFsp)\r
587TempRamInitApiL4:\r
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
595\r
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
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
663 #\r
664 # EAX holds the API index\r
665 #\r
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
674 movl $0x080000003, %eax\r
675 jmp FspApiCommonExit\r
676\r
677FspApiCommonL0:\r
678 #\r
679 # Verify the calling condition\r
680 #\r
681 pushal\r
682 pushl %eax\r
683 call ASM_PFX(FspApiCallingCheck)\r
684 addl $0x04, %esp\r
685 cmpl $0x00, %eax\r
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
698\r
699FspApiCommonL2:\r
700 #\r
701 # FspInit and FspMemoryInit APIs, setup the initial stack frame\r
702 # \r
703 \r
704 #\r
705 # Store the address in FSP which will return control to the BL\r
706 #\r
707 pushl $FspApiCommonExit\r
708\r
709 #\r
710 # Create a Task Frame in the stack for the Boot Loader\r
711 #\r
712 pushfl # 2 pushf for 4 byte alignment\r
713 cli\r
714 pushal\r
715\r
716 #\r
717 # Reserve 8 bytes for IDT save/restore\r
718 #\r
719 subl $0x08, %esp\r
720 sidt (%esp)\r
721\r
722 #\r
723 # Setup new FSP stack\r
724 #\r
725 movl %esp, %edi\r
726 movl PcdGet32(PcdTemporaryRamBase), %esp\r
727 addl PcdGet32(PcdTemporaryRamSize), %esp\r
728 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp\r
729\r
730 #\r
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
739\r
740 #\r
741 # Pass entry point of the PEI core\r
742 #\r
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
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
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
762\r
763 #\r
764 # Pass stack base and size into the PEI Core\r
765 #\r
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
771\r
772 #\r
773 # Pass Control into the PEI Core\r
774 #\r
775 call ASM_PFX(SecStartup)\r
776\r
777FspApiCommonExit:\r
778 ret\r
779\r
780\r