]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
rename XXXDflt to XXXDefault (expand for better readability)
[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# FspSelfCheckDefault\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(FspSelfCheckDefault)\r
196ASM_PFX(FspSelfCheckDefault):\r
197 #\r
198 # Save return address to EBP\r
199 #\r
200 movl %eax, %ebp\r
201 xorl %eax, %eax\r
202\r
203FspSelfCheckDefaultExit:\r
204 jmp *%ebp\r
205\r
206\r
207#------------------------------------------------------------------------------\r
208# SecPlatformInitDefault\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(SecPlatformInitDefault)\r
218ASM_PFX(SecPlatformInitDefault):\r
219 #\r
220 # Save return address to EBP\r
221 #\r
222 movl %eax, %ebp\r
223 xorl %eax, %eax\r
224\r
225SecPlatformInitDefaultExit:\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 %mm7, %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#----------------------------------------------------------------------------\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
488 LOAD_EDX\r
489 pushl %edx\r
490 LOAD_EAX\r
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
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
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
548\r
549 #\r
550 # CPUID/DeviceID check\r
551 #\r
552 movl $TempRamInitApiL0, %eax\r
553 jmp ASM_PFX(FspSelfCheckDefault) # @note: ESP can not be changed.\r
554TempRamInitApiL0:\r
555 cmpl $0x00, %eax\r
556 jnz NemInitExit\r
557\r
558 #\r
559 # Sec Platform Init\r
560 #\r
561 movl $TempRamInitApiL1, %esi #CALL_MMX SecPlatformInit\r
562 movd %mm7, %esi\r
563 jmp ASM_PFX(SecPlatformInit)\r
564TempRamInitApiL1:\r
565 cmpl $0x00, %eax\r
566 jnz NemInitExit\r
567\r
568 #\r
569 # Load microcode\r
570 #\r
571 LOAD_ESP\r
572 movl $TempRamInitApiL2, %esi #CALL_MMX LoadUcode\r
573 movd %mm7, %esi\r
574 jmp ASM_PFX(LoadUcode)\r
575TempRamInitApiL2:\r
576 cmpl $0x00, %eax\r
577 jnz NemInitExit\r
578\r
579 #\r
580 # Call Sec CAR Init\r
581 #\r
582 LOAD_ESP\r
583 movl $TempRamInitApiL3, %esi #CALL_MMX SecCarInit\r
584 movd %mm7, %esi\r
585 jmp ASM_PFX(SecCarInit)\r
586TempRamInitApiL3:\r
587 cmpl $0x00, %eax\r
588 jnz NemInitExit\r
589\r
590 #\r
591 # EstablishStackFsp\r
592 #\r
593 LOAD_ESP\r
594 movl $TempRamInitApiL4, %esi #CALL_MMX EstablishStackFsp\r
595 movd %mm7, %esi\r
596 jmp ASM_PFX(EstablishStackFsp)\r
597TempRamInitApiL4:\r
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
605\r
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
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
673 #\r
674 # EAX holds the API index\r
675 #\r
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
684 movl $0x080000003, %eax\r
685 jmp FspApiCommonExit\r
686\r
687FspApiCommonL0:\r
688 #\r
689 # Verify the calling condition\r
690 #\r
691 pushal\r
692 pushl %eax\r
693 call ASM_PFX(FspApiCallingCheck)\r
694 addl $0x04, %esp\r
695 cmpl $0x00, %eax\r
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
708\r
709FspApiCommonL2:\r
710 #\r
711 # FspInit and FspMemoryInit APIs, setup the initial stack frame\r
712 # \r
713 \r
714 #\r
715 # Store the address in FSP which will return control to the BL\r
716 #\r
717 pushl $FspApiCommonExit\r
718\r
719 #\r
720 # Create a Task Frame in the stack for the Boot Loader\r
721 #\r
722 pushfl # 2 pushf for 4 byte alignment\r
723 cli\r
724 pushal\r
725\r
726 #\r
727 # Reserve 8 bytes for IDT save/restore\r
728 #\r
729 subl $0x08, %esp\r
730 sidt (%esp)\r
731\r
732 #\r
733 # Setup new FSP stack\r
734 #\r
735 movl %esp, %edi\r
736 movl PcdGet32(PcdTemporaryRamBase), %esp\r
737 addl PcdGet32(PcdTemporaryRamSize), %esp\r
738 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp\r
739\r
740 #\r
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
749\r
750 #\r
751 # Pass entry point of the PEI core\r
752 #\r
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
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
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
772\r
773 #\r
774 # Pass stack base and size into the PEI Core\r
775 #\r
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
781\r
782 #\r
783 # Pass Control into the PEI Core\r
784 #\r
785 call ASM_PFX(SecStartup)\r
786\r
787FspApiCommonExit:\r
788 ret\r
789\r
790\r