]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
MdeModulePkg: Update library class name of PlatformHookLibSerialPortPpi.inf
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.s
CommitLineData
c8ec22a2
JY
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
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
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
c8ec22a2
JY
195#------------------------------------------------------------------------------\r
196ASM_GLOBAL ASM_PFX(FspSelfCheckDflt)\r
197ASM_PFX(FspSelfCheckDflt):\r
975f1c64 198 #\r
c8ec22a2 199 # Save return address to EBP\r
975f1c64 200 #\r
c8ec22a2
JY
201 movl %eax, %ebp\r
202 xorl %eax, %eax\r
975f1c64
JY
203\r
204FspSelfCheckDfltExit:\r
c8ec22a2 205 jmp *%ebp\r
c8ec22a2 206\r
975f1c64
JY
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
c8ec22a2
JY
217#------------------------------------------------------------------------------\r
218ASM_GLOBAL ASM_PFX(PlatformBasicInitDflt)\r
219ASM_PFX(PlatformBasicInitDflt):\r
975f1c64 220 #\r
c8ec22a2 221 # Save return address to EBP\r
975f1c64 222 #\r
c8ec22a2
JY
223 movl %eax, %ebp\r
224 xorl %eax, %eax\r
975f1c64
JY
225\r
226PlatformBasicInitDfltExit:\r
c8ec22a2 227 jmp *%ebp\r
975f1c64 228\r
c8ec22a2 229\r
975f1c64
JY
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
c8ec22a2
JY
242#------------------------------------------------------------------------------\r
243ASM_GLOBAL ASM_PFX(LoadUcode)\r
975f1c64 244ASM_PFX(LoadUcode): \r
c8ec22a2
JY
245 #\r
246 # Save return address to EBP\r
975f1c64 247 #\r
c8ec22a2 248 movl %eax, %ebp\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
JY
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
975f1c64
JY
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
c8ec22a2
JY
485\r
486 #\r
487 # CPUID/DeviceID check\r
488 #\r
975f1c64
JY
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
c8ec22a2
JY
494\r
495 #\r
496 # Platform Basic Init.\r
497 #\r
975f1c64
JY
498 movl $TempRamInitApiL1, %eax\r
499 jmp ASM_PFX(PlatformBasicInitDflt)\r
500TempRamInitApiL1:\r
501 cmpl $0x00, %eax\r
502 jnz NemInitExit\r
c8ec22a2
JY
503\r
504 #\r
505 # Load microcode\r
506 #\r
975f1c64
JY
507 movl $TempRamInitApiL2, %eax\r
508 addl $0x04, %esp\r
509 jmp LoadUcode\r
510\r
511TempRamInitApiL2:\r
c8ec22a2 512 LOAD_ESP\r
975f1c64
JY
513 cmpl $0x00, %eax\r
514 jnz NemInitExit\r
c8ec22a2
JY
515\r
516 #\r
517 # Call platform NEM init\r
975f1c64
JY
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
c8ec22a2
JY
526\r
527 #\r
528 # Save parameter pointer in edx\r
529 #\r
975f1c64 530 movl 4(%esp), %edx\r
c8ec22a2
JY
531\r
532 #\r
533 # Enable FSP STACK\r
534 #\r
975f1c64
JY
535 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp\r
536 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %esp\r
c8ec22a2 537\r
975f1c64
JY
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
c8ec22a2 544\r
c8ec22a2
JY
545 #\r
546 # Save API entry/exit timestamp into stack\r
547 #\r
975f1c64
JY
548 pushl $DATA_LEN_OF_PER0 # Size of the data region\r
549 pushl $0x30524550 # Signature of the data region 'PER0'\r
c8ec22a2 550 rdtsc\r
975f1c64
JY
551 pushl %edx\r
552 pushl %eax\r
553 LOAD_EAX\r
554 LOAD_EDX\r
555 pushl %edx\r
556 pushl %eax\r
c8ec22a2
JY
557\r
558 #\r
559 # Terminator for the data on stack\r
560 #\r
975f1c64 561 pushl $0x00\r
c8ec22a2
JY
562\r
563 #\r
564 # Set ECX/EDX to the bootloader temporary memory range\r
565 #\r
975f1c64
JY
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
c8ec22a2 570\r
975f1c64 571 xorl %eax, %eax\r
c8ec22a2
JY
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
975f1c64 579\r
c8ec22a2
JY
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
975f1c64 595 popl %eax\r
c8ec22a2 596 cmpl $0x087654321, %eax\r
975f1c64 597 jz FspInitApiL0\r
c8ec22a2 598 movl $0x080000003, %eax\r
975f1c64 599 jmp FspInitApiexit\r
c8ec22a2 600\r
975f1c64 601FspInitApiL0:\r
c8ec22a2
JY
602 #\r
603 # Additional check\r
604 #\r
605 pusha\r
975f1c64 606 pushl $0x01\r
c8ec22a2 607 call ASM_PFX(FspApiCallingCheck)\r
975f1c64
JY
608 addl $0x04, %esp\r
609 movl %eax, 28(%esp)\r
c8ec22a2 610 popa\r
975f1c64
JY
611 cmpl $0x00, %eax\r
612 jz FspInitApiL1\r
613 jmp FspInitApiexit\r
c8ec22a2 614\r
975f1c64 615FspInitApiL1:\r
c8ec22a2
JY
616 #\r
617 # Store the address in FSP which will return control to the BL\r
618 #\r
975f1c64 619 pushl $FspInitApiexit\r
c8ec22a2
JY
620\r
621 #\r
622 # Create a Task Frame in the stack for the Boot Loader\r
623 #\r
c8ec22a2
JY
624 pushfl # 2 pushf for 4 byte alignment\r
625 cli\r
626 pushal\r
627\r
975f1c64 628 #\r
c8ec22a2 629 # Reserve 8 bytes for IDT save/restore\r
975f1c64
JY
630 #\r
631 subl $0x08, %esp\r
632 sidt (%esp)\r
c8ec22a2
JY
633\r
634 #\r
635 # Setup new FSP stack\r
636 #\r
975f1c64
JY
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
c8ec22a2 641\r
c8ec22a2
JY
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
975f1c64
JY
650 movl ASM_PFX(FspImageSizeOffset), %edi\r
651 movl (%eax, %edi), %edi\r
652 addl %eax, %edi\r
c8ec22a2 653 subl $0x20, %edi\r
975f1c64 654 addl (%edi), %eax\r
c8ec22a2
JY
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
975f1c64 684FspInitApiexit:\r
c8ec22a2
JY
685 ret\r
686\r
c8ec22a2
JY
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
975f1c64 701 popl %eax\r
c8ec22a2 702 cmpl $0x087654321, %eax\r
975f1c64 703 jz NotifyPhaseApiL0\r
c8ec22a2 704 movl $0x080000003, %eax\r
975f1c64 705 jmp NotifyPhaseApiErrExit\r
c8ec22a2 706\r
975f1c64 707NotifyPhaseApiL0:\r
c8ec22a2
JY
708 #\r
709 # Verify the calling condition\r
710 #\r
711 pusha\r
975f1c64
JY
712 pushl $0x02\r
713 call ASM_PFX(FspApiCallingCheck)\r
714 addl $0x04, %esp\r
715 movl %eax, 28(%esp)\r
c8ec22a2
JY
716 popa\r
717\r
975f1c64
JY
718 cmpl $0x00, %eax\r
719 jz NotifyPhaseApiL1\r
c8ec22a2
JY
720\r
721 #\r
722 # Error return\r
723 #\r
975f1c64 724NotifyPhaseApiErrExit:\r
c8ec22a2
JY
725 ret\r
726\r
975f1c64 727NotifyPhaseApiL1:\r
c8ec22a2
JY
728 jmp ASM_PFX(Pei2LoaderSwitchStack)\r
729\r
c8ec22a2
JY
730\r
731\r
732#END\r