]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
IntelFspPkg: Replace BSD License with BSD+Patent License
[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# SPDX-License-Identifier: BSD-2-Clause-Patent\r
5#\r
6# Abstract:\r
7#\r
8# Provide FSP API entry points.\r
9#\r
10#------------------------------------------------------------------------------\r
11\r
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
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
31\r
32\r
33ExtSigHdr:\r
34.equ ExtSigHdrCount, 0x0000\r
35.equ ExtSigHdrChecksum, 0x0004\r
36.equ ExtSigHdrRsvd, 0x0008\r
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
47LoadMicrocodeParams:\r
48.equ MicrocodeCodeAddr, 0x0000\r
49.equ MicrocodeCodeSize, 0x0004\r
50LoadMicrocodeParamsEnd:\r
51\r
52\r
53\r
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
59#\r
60 pinsrw $0x02, %ebx, %xmm7\r
61 ror $0x10, %ebx\r
62 pinsrw $0x03, %ebx, %xmm7\r
63 ror $0x10, %ebx\r
64#\r
65 pinsrw $0x04, %esi, %xmm7\r
66 ror $0x10, %esi\r
67 pinsrw $0x05, %esi, %xmm7\r
68 ror $0x10, %esi\r
69#\r
70 pinsrw $0x06, %edi, %xmm7\r
71 ror $0x10, %edi\r
72 pinsrw $0x07, %edi, %xmm7\r
73 ror $0x10, %edi\r
74#\r
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
80\r
81.macro LOAD_REGS\r
82 pshufd $0xe4, %xmm7, %xmm7\r
83 movd %xmm7, %ebp \r
84 pshufd $0xe4, %xmm7, %xmm7\r
85#\r
86 pshufd $0x39, %xmm7, %xmm7\r
87 movd %xmm7, %ebx\r
88 pshufd $0x93, %xmm7, %xmm7\r
89#\r
90 pshufd $0x4e, %xmm7, %xmm7\r
91 movd %xmm7, %esi\r
92 pshufd $0x4e, %xmm7, %xmm7\r
93#\r
94 pshufd $0x93, %xmm7, %xmm7\r
95 movd %xmm7, %edi\r
96 pshufd $0x39, %xmm7, %xmm7\r
97#\r
98 movd %xmm6, %esp\r
99.endm\r
100\r
101.macro LOAD_EAX\r
102 pshufd $0x39, %xmm6, %xmm6\r
103 movd %xmm6, %eax\r
104 pshufd $0x93, %xmm6, %xmm6\r
105.endm\r
106\r
107.macro LOAD_EDX\r
108 pshufd $0xe4, %xmm6, %xmm6\r
109 movd %xmm6, %edx\r
110 pshufd $0xe4, %xmm6, %xmm6\r
111.endm\r
112\r
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
125.endm\r
126\r
127.macro LOAD_ESP\r
128 movd %xmm6, %esp\r
129.endm\r
130\r
131.macro ENABLE_SSE\r
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
192.endm\r
193\r
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
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
212ASM_GLOBAL ASM_PFX(AsmGetFspBaseAddress)\r
213ASM_GLOBAL ASM_PFX(AsmGetFspInfoHeader)\r
214ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)\r
215ASM_GLOBAL ASM_PFX(Loader2PeiSwitchStack)\r
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
225#------------------------------------------------------------------------------\r
226# SecPlatformInitDefault\r
227# Inputs:\r
228# mm7 -> Return address\r
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
234#------------------------------------------------------------------------------\r
235ASM_GLOBAL ASM_PFX(SecPlatformInitDefault)\r
236ASM_PFX(SecPlatformInitDefault):\r
237 #\r
238 # Save return address to EBP\r
239 #\r
240 movd %mm7, %ebp\r
241 xorl %eax, %eax\r
242\r
243SecPlatformInitDefaultExit:\r
244 jmp *%ebp\r
245\r
246\r
247#------------------------------------------------------------------------------\r
248# LoadMicrocodeDefault\r
249#\r
250# Inputs:\r
251# esp -> LoadMicrocodeParams pointer\r
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
259#------------------------------------------------------------------------------\r
260ASM_GLOBAL ASM_PFX(LoadMicrocodeDefault)\r
261ASM_PFX(LoadMicrocodeDefault):\r
262 #\r
263 # Save return address to EBP\r
264 #\r
265 movd %mm7, %ebp\r
266\r
267 cmpl $0x00, %esp\r
268 jz ParamError\r
269 movl 4(%esp), %eax #dword ptr [] Parameter pointer\r
270 cmpl $0x00, %eax\r
271 jz ParamError\r
272 movl %eax, %esp\r
273 movl MicrocodeCodeAddr(%esp), %esi\r
274 cmpl $0x00, %esi\r
275 jnz CheckMainHeader\r
276\r
277ParamError:\r
278 movl $0x080000002, %eax\r
279 jmp LoadMicrocodeExit\r
280\r
281CheckMainHeader:\r
282 #\r
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
287 #\r
288 movl $0x01, %eax\r
289 cpuid\r
290 movl %eax, %ebx\r
291 movl $MSR_IA32_PLATFORM_ID, %ecx\r
292 rdmsr\r
293 movl %edx, %ecx\r
294 shrl $0x12, %ecx # shift (50d-32d=18d=0x12) bits\r
295 andl $0x07, %ecx # platform id at bit[52..50]\r
296 movl $0x01, %edx\r
297 shll %cl,%edx\r
298\r
299 #\r
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
305 #\r
306\r
307 #\r
308 # Check for valid microcode header\r
309 # Minimal test checking for header version and loader version as 1\r
310 #\r
311 movl $0x01, %eax\r
312 cmpl %eax, MicrocodeHdrVersion(%esi)\r
313 jne AdvanceFixedSize\r
314 cmpl %eax, MicrocodeHdrLoader(%esi)\r
315 jne AdvanceFixedSize\r
316\r
317 #\r
318 # Check if signature and plaform ID match\r
319 #\r
320 cmpl MicrocodeHdrProcessor(%esi), %ebx\r
321 jne LoadMicrocodeL0\r
322 testl MicrocodeHdrFlags(%esi), %edx\r
323 jnz LoadCheck #Jif signature and platform ID match\r
324\r
325LoadMicrocodeL0:\r
326 #\r
327 # Check if extended header exists\r
328 # First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid\r
329 #\r
330 xorl %eax, %eax\r
331 cmpl %eax, MicrocodeHdrTotalSize(%esi)\r
332 je NextMicrocode\r
333 cmpl %eax, MicrocodeHdrDataSize(%esi)\r
334 je NextMicrocode\r
335\r
336 #\r
337 # Then verify total size - sizeof header > data size\r
338 #\r
339 movl MicrocodeHdrTotalSize(%esi), %ecx\r
340 subl $MicrocodeHdrLength, %ecx\r
341 cmpl MicrocodeHdrDataSize(%esi), %ecx\r
342 jle NextMicrocode\r
343\r
344 #\r
345 # Set edi -> extended header\r
346 #\r
347 movl %esi, %edi\r
348 addl $MicrocodeHdrLength, %edi\r
349 addl MicrocodeHdrDataSize(%esi), %edi\r
350\r
351 #\r
352 # Get count of extended structures\r
353 #\r
354 movl ExtSigHdrCount(%edi), %ecx\r
355\r
356 #\r
357 # Move pointer to first signature structure\r
358 #\r
359 addl ExtSigHdrLength, %edi\r
360\r
361CheckExtSig:\r
362 #\r
363 # Check if extended signature and platform ID match\r
364 #\r
365 cmpl %ebx, ExtSigProcessor(%edi)\r
366 jne LoadMicrocodeL1\r
367 test %edx, ExtSigFlags(%edi)\r
368 jnz LoadCheck # Jif signature and platform ID match\r
369LoadMicrocodeL1:\r
370 #\r
371 # Check if any more extended signatures exist\r
372 #\r
373 addl $ExtSigLength, %edi\r
374 loop CheckExtSig\r
375\r
376NextMicrocode:\r
377 #\r
378 # Advance just after end of this microcode\r
379 #\r
380 xorl %eax, %eax\r
381 cmpl %eax, MicrocodeHdrTotalSize(%esi)\r
382 je LoadMicrocodeL2\r
383 addl MicrocodeHdrTotalSize(%esi), %esi\r
384 jmp CheckAddress\r
385LoadMicrocodeL2:\r
386 addl $0x800, %esi #add esi, dword ptr 2048\r
387 jmp CheckAddress\r
388\r
389AdvanceFixedSize:\r
390 #\r
391 # Advance by 4X dwords\r
392 #\r
393 addl $0x400, %esi #add esi, dword ptr 1024\r
394\r
395CheckAddress:\r
396 #\r
397 # Is valid Microcode start point ?\r
398 #\r
399 cmpl $0x0ffffffff, MicrocodeHdrVersion(%esi)\r
400\r
401 #\r
402 # Is automatic size detection ?\r
403 #\r
404 movl MicrocodeCodeSize(%esp), %eax\r
405 cmpl $0x0ffffffff, %eax\r
406 jz LoadMicrocodeL3\r
407 #\r
408 # Address >= microcode region address + microcode region size?\r
409 #\r
410 addl MicrocodeCodeAddr(%esp), %eax\r
411\r
412 cmpl %eax, %esi\r
413 jae Done #Jif address is outside of microcode region\r
414 jmp CheckMainHeader\r
415\r
416LoadMicrocodeL3:\r
417LoadCheck:\r
418 #\r
419 # Get the revision of the current microcode update loaded\r
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
425\r
426 movl $0x01, %eax\r
427 cpuid\r
428 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
429 rdmsr # Get current microcode signature\r
430\r
431 #\r
432 # Verify this microcode update is not already loaded\r
433 #\r
434 cmpl %edx, MicrocodeHdrRevision(%esi)\r
435 je Continue\r
436\r
437LoadMicrocode0:\r
438 #\r
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
443 #\r
444 movl %esi, %eax\r
445 addl $MicrocodeHdrLength, %eax\r
446 xorl %edx, %edx\r
447 movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx\r
448 wrmsr\r
449 movl $0x01, %eax\r
450 cpuid\r
451\r
452Continue:\r
453 jmp NextMicrocode\r
454\r
455Done:\r
456 movl $0x01, %eax\r
457 cpuid\r
458 movl $MSR_IA32_BIOS_SIGN_ID, %ecx\r
459 rdmsr # Get current microcode signature\r
460 xorl %eax, %eax\r
461 cmpl $0x00, %edx\r
462 jnz LoadMicrocodeExit\r
463 movl $0x08000000E, %eax\r
464\r
465LoadMicrocodeExit:\r
466 jmp *%ebp\r
467\r
468\r
469#----------------------------------------------------------------------------\r
470# EstablishStackFsp\r
471#\r
472#----------------------------------------------------------------------------\r
473ASM_GLOBAL ASM_PFX(EstablishStackFsp)\r
474ASM_PFX(EstablishStackFsp):\r
475 #\r
476 # Save parameter pointer in edx\r
477 #\r
478 movl 4(%esp), %edx\r
479\r
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
490 pushl 4(%edx) # Microcode size\r
491 pushl (%edx) # Microcode base\r
492\r
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
498 LOAD_EDX\r
499 pushl %edx\r
500 LOAD_EAX\r
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
508 #\r
509 push $0x00\r
510\r
511 #\r
512 # Set ECX/EDX to the BootLoader temporary memory range\r
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
520\r
521 movd %mm7, %esi #RET_ESI\r
522 jmp *%esi\r
523\r
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
545 # Save timestamp into XMM6\r
546 #\r
547 rdtsc\r
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
558\r
559 #\r
560 # Sec Platform Init\r
561 #\r
562 movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit\r
563 movd %esi, %mm7\r
564 .weak ASM_PFX(SecPlatformInit)\r
565 .set ASM_PFX(SecPlatformInit), ASM_PFX(SecPlatformInitDefault)\r
566 jmp ASM_PFX(SecPlatformInit)\r
567TempRamInitApiL1:\r
568 cmpl $0x00, %eax\r
569 jnz NemInitExit\r
570\r
571 #\r
572 # Load microcode\r
573 #\r
574 LOAD_ESP\r
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
580TempRamInitApiL2:\r
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
583\r
584 #\r
585 # Call Sec CAR Init\r
586 #\r
587 LOAD_ESP\r
588 movl $TempRamInitApiL3, %esi #CALL_MMX SecCarInit\r
589 movd %esi, %mm7\r
590 jmp ASM_PFX(SecCarInit)\r
591TempRamInitApiL3:\r
592 cmpl $0x00, %eax\r
593 jnz NemInitExit\r
594\r
595 #\r
596 # EstablishStackFsp\r
597 #\r
598 LOAD_ESP\r
599 movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp\r
600 movd %esi, %mm7\r
601 jmp ASM_PFX(EstablishStackFsp)\r
602TempRamInitApiL4:\r
603\r
604 LOAD_EAX_MICROCODE_RET_STATUS #Restore microcode status if no CAR init error.\r
605\r
606NemInitExit:\r
607 #\r
608 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6\r
609 #\r
610 LOAD_REGS\r
611 ret\r
612\r
613\r
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
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
681 #\r
682 # EAX holds the API index\r
683 #\r
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
692 movl $0x080000003, %eax\r
693 jmp FspApiCommonExit\r
694\r
695FspApiCommonL0:\r
696 #\r
697 # Verify the calling condition\r
698 #\r
699 pushal\r
700 pushl 36(%esp) #push ApiParam [esp + 4 * 8 + 4]\r
701 pushl %eax #push ApiIdx\r
702 call ASM_PFX(FspApiCallingCheck)\r
703 addl $0x08, %esp\r
704 cmpl $0x00, %eax\r
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
716 call ASM_PFX(AsmGetFspInfoHeader)\r
717 jmp Loader2PeiSwitchStack\r
718\r
719FspApiCommonL2:\r
720 #\r
721 # FspInit and FspMemoryInit APIs, setup the initial stack frame\r
722 # \r
723 \r
724 #\r
725 # Place holder to store the FspInfoHeader pointer\r
726 #\r
727 pushl %eax\r
728\r
729 #\r
730 # Update the FspInfoHeader pointer\r
731 #\r
732 pushl %eax\r
733 call ASM_PFX(AsmGetFspInfoHeader)\r
734 movl %eax, 4(%esp)\r
735 popl %eax\r
736\r
737 #\r
738 # Create a Task Frame in the stack for the Boot Loader\r
739 #\r
740 pushfl # 2 pushf for 4 byte alignment\r
741 cli\r
742 pushal\r
743\r
744 #\r
745 # Reserve 8 bytes for IDT save/restore\r
746 #\r
747 subl $0x08, %esp\r
748 sidt (%esp)\r
749\r
750 #\r
751 # Setup new FSP stack\r
752 #\r
753 movl %esp, %edi\r
754 movl PcdGet32(PcdTemporaryRamBase), %esp\r
755 addl PcdGet32(PcdTemporaryRamSize), %esp\r
756 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp\r
757\r
758 #\r
759 # Pass the API Idx to SecStartup\r
760 #\r
761 pushl %eax\r
762 \r
763 #\r
764 # Pass the BootLoader stack to SecStartup\r
765 #\r
766 pushl %edi\r
767\r
768 #\r
769 # Pass entry point of the PEI core\r
770 #\r
771 call ASM_PFX(AsmGetFspBaseAddress)\r
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
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
781 # For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and\r
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
785 call ASM_PFX(AsmGetFspBaseAddress)\r
786 movl %eax, %edi\r
787 call ASM_PFX(GetBootFirmwareVolumeOffset)\r
788 addl %edi, %eax\r
789 pushl %eax\r
790\r
791 #\r
792 # Pass stack base and size into the PEI Core\r
793 #\r
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
799\r
800 #\r
801 # Pass Control into the PEI Core\r
802 #\r
803 call ASM_PFX(SecStartup)\r
804 addl $4, %esp\r
805FspApiCommonExit:\r
806 ret\r
807\r