]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.s
MdeModulePkg: Update library class name of PlatformHookLibSerialPortPpi.inf
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.s
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
4 # This program and the accompanying materials
5 # are licensed and made available under the terms and conditions of the BSD License
6 # which accompanies this distribution. The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php.
8 #
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 #
12 # Abstract:
13 #
14 # Provide FSP API entry points.
15 #
16 #------------------------------------------------------------------------------
17
18 #.INCLUDE "UcodeLoadGcc.inc" - begin
19
20 .equ MSR_IA32_PLATFORM_ID, 0x00000017
21 .equ MSR_IA32_BIOS_UPDT_TRIG, 0x00000079
22 .equ MSR_IA32_BIOS_SIGN_ID, 0x0000008b
23
24 Ucode:
25 .equ UcodeVersion, 0x0000
26 .equ UcodeRevision, 0x0004
27 .equ UcodeDate, 0x0008
28 .equ UcodeProcessor, 0x000C
29 .equ UcodeChecksum, 0x0010
30 .equ UcodeLoader, 0x0014
31 .equ UcodeRsvd, 0x0018
32 UcodeEnd:
33
34 UcodeHdr:
35 .equ UcodeHdrVersion, 0x0000
36 .equ UcodeHdrRevision, 0x0004
37 .equ UcodeHdrDate, 0x0008
38 .equ UcodeHdrProcessor, 0x000c
39 .equ UcodeHdrChecksum, 0x0010
40 .equ UcodeHdrLoader, 0x0014
41 .equ UcodeHdrFlags, 0x0018
42 .equ UcodeHdrDataSize, 0x001C
43 .equ UcodeHdrTotalSize, 0x0020
44 .equ UcodeHdrRsvd, 0x0024
45 UcodeHdrEnd:
46 .equ UcodeHdrLength, 0x0030 # UcodeHdrLength = UcodeHdrEnd - UcodeHdr
47
48
49 ExtSigHdr:
50 .equ ExtSigHdrCount, 0x0000
51 .equ ExtSigHdrChecksum, 0x0004
52 .equ rsvd, 0x0008
53 ExtSigHdrEnd:
54 .equ ExtSigHdrLength, 0x0014 #ExtSigHdrLength = ExtSigHdrEnd - ExtSigHdr
55
56 ExtSig:
57 .equ ExtSigProcessor, 0x0000
58 .equ ExtSigFlags, 0x0004
59 .equ ExtSigChecksum, 0x0008
60 ExtSigEnd:
61 .equ ExtSigLength, 0x000C #ExtSigLength = ExtSigEnd - ExtSig
62
63 LoadUcodeParams:
64 .equ LoadUcodeParamsUcodeCodeAddr, 0x0000
65 .equ LoadUcodeParamsUcodeCodeSize, 0x0004
66 LoadUcodeParamsEnd:
67
68 #.INCLUDE "UcodeLoadGcc.inc" - end
69
70 #.INCLUDE "SaveRestoreSseGcc.inc" - begin
71
72 .macro SAVE_REGS
73 pinsrw $0x00, %ebp, %xmm7
74 ror $0x10, %ebp
75 pinsrw $0x01, %ebp, %xmm7
76 ror $0x10, %ebp
77 #
78 pinsrw $0x02, %ebx, %xmm7
79 ror $0x10, %ebx
80 pinsrw $0x03, %ebx, %xmm7
81 ror $0x10, %ebx
82 #
83 pinsrw $0x04, %esi, %xmm7
84 ror $0x10, %esi
85 pinsrw $0x05, %esi, %xmm7
86 ror $0x10, %esi
87 #
88 pinsrw $0x06, %edi, %xmm7
89 ror $0x10, %edi
90 pinsrw $0x07, %edi, %xmm7
91 ror $0x10, %edi
92 #
93 pinsrw $0x00, %esp, %xmm6
94 ror $0x10, %esp
95 pinsrw $0x01, %esp, %xmm6
96 ror $0x10, %esp
97 .endm
98
99 .macro LOAD_REGS
100 pshufd $0xe4, %xmm7, %xmm7
101 movd %xmm7, %ebp
102 pshufd $0xe4, %xmm7, %xmm7
103 #
104 pshufd $0x39, %xmm7, %xmm7
105 movd %xmm7, %ebx
106 pshufd $0x93, %xmm7, %xmm7
107 #
108 pshufd $0x4e, %xmm7, %xmm7
109 movd %xmm7, %esi
110 pshufd $0x4e, %xmm7, %xmm7
111 #
112 pshufd $0x93, %xmm7, %xmm7
113 movd %xmm7, %edi
114 pshufd $0x39, %xmm7, %xmm7
115 #
116 movd %xmm6, %esp
117 .endm
118
119 .macro LOAD_EAX
120 pshufd $0x39, %xmm6, %xmm6
121 movd %xmm6, %eax
122 pshufd $0x93, %xmm6, %xmm6
123 .endm
124
125 .macro LOAD_EDX
126 pshufd $0xe4, %xmm6, %xmm6
127 movd %xmm6, %edx
128 pshufd $0xe4, %xmm6, %xmm6
129 .endm
130
131 .macro SAVE_EAX
132 pinsrw $0x02, %eax, %xmm6
133 ror $0x10, %eax
134 pinsrw $0x03, %eax, %xmm6
135 ror $0x10, %eax
136 .endm
137
138 .macro SAVE_EDX
139 pinsrw $0x04, %edx, %xmm6
140 ror $0x10, %edx
141 pinsrw $0x05, %edx, %xmm6
142 ror $0x10, %edx
143 .endm
144
145 .macro LOAD_ESP
146 movd %xmm6, %esp
147 .endm
148
149 .macro ENABLE_SSE
150 movl %cr4, %eax
151 orl $0x00000600, %eax # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
152 movl %eax,%cr4
153 .endm
154
155 #.INCLUDE "SaveRestoreSseGcc.inc" - end
156
157
158 #
159 # Following are fixed PCDs
160 #
161 ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase)
162 ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize)
163 ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
164
165 #
166 # Following functions will be provided in C
167 #
168 ASM_GLOBAL ASM_PFX(FspImageSizeOffset)
169 ASM_GLOBAL ASM_PFX(SecStartup)
170 ASM_GLOBAL ASM_PFX(FspApiCallingCheck)
171
172 #
173 # Following functions will be provided in PlatformSecLib
174 #
175 ASM_GLOBAL ASM_PFX(GetBootFirmwareVolumeOffset)
176 ASM_GLOBAL ASM_PFX(Pei2LoaderSwitchStack)
177
178
179 #
180 # Define the data length that we saved on the stack top
181 #
182 .equ DATA_LEN_OF_PER0, 0x018
183 .equ DATA_LEN_OF_MCUD, 0x018
184 .equ DATA_LEN_AT_STACK_TOP, (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
185
186 #------------------------------------------------------------------------------
187 # FspSelfCheckDflt
188 # Inputs:
189 # eax -> Return address
190 # Outputs:
191 # eax -> 0 - Successful, Non-zero - Failed.
192 # Register Usage:
193 # eax is cleared and ebp is used for return address.
194 # All others reserved.
195 #------------------------------------------------------------------------------
196 ASM_GLOBAL ASM_PFX(FspSelfCheckDflt)
197 ASM_PFX(FspSelfCheckDflt):
198 #
199 # Save return address to EBP
200 #
201 movl %eax, %ebp
202 xorl %eax, %eax
203
204 FspSelfCheckDfltExit:
205 jmp *%ebp
206
207
208 #------------------------------------------------------------------------------
209 # PlatformBasicInitDflt
210 # Inputs:
211 # eax -> Return address
212 # Outputs:
213 # eax -> 0 - Successful, Non-zero - Failed.
214 # Register Usage:
215 # eax is cleared and ebp is used for return address.
216 # All others reserved.
217 #------------------------------------------------------------------------------
218 ASM_GLOBAL ASM_PFX(PlatformBasicInitDflt)
219 ASM_PFX(PlatformBasicInitDflt):
220 #
221 # Save return address to EBP
222 #
223 movl %eax, %ebp
224 xorl %eax, %eax
225
226 PlatformBasicInitDfltExit:
227 jmp *%ebp
228
229
230 #------------------------------------------------------------------------------
231 # LoadUcode
232 #
233 # Inputs:
234 # esp -> LOAD_UCODE_PARAMS pointer
235 # Register Usage:
236 # esp Preserved
237 # All others destroyed
238 # Assumptions:
239 # No memory available, stack is hard-coded and used for return address
240 # Executed by SBSP and NBSP
241 # Beginning of microcode update region starts on paragraph boundary
242 #------------------------------------------------------------------------------
243 ASM_GLOBAL ASM_PFX(LoadUcode)
244 ASM_PFX(LoadUcode):
245 #
246 # Save return address to EBP
247 #
248 movl %eax, %ebp
249 cmpl $0x00, %esp
250 jz ParamError
251 movl (%esp), %eax #dword ptr [] Parameter pointer
252 cmpl $0x00, %eax
253 jz ParamError
254 movl %eax, %esp
255 movl LoadUcodeParamsUcodeCodeAddr(%esp), %esi #mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
256 cmpl $0x00, %esi
257 jnz CheckMainHeader
258
259 ParamError:
260 movl $0x080000002, %eax
261 jmp LoadUcodeExit
262
263 CheckMainHeader:
264 #
265 # Get processor signature and platform ID from the installed processor
266 # and save into registers for later use
267 # ebx = processor signature
268 # edx = platform ID
269 #
270 movl $0x01, %eax
271 cpuid
272 movl %eax, %ebx
273 movl $MSR_IA32_PLATFORM_ID, %ecx
274 rdmsr
275 movl %edx, %ecx
276 shrl $0x12, %ecx #($50-$32)
277 andl $0x07, %ecx
278 movl $0x01, %edx
279 shll %cl,%edx
280
281 #
282 # Current register usage
283 # esp -> stack with paramters
284 # esi -> microcode update to check
285 # ebx = processor signature
286 # edx = platform ID
287 #
288
289 #
290 # Check for valid microcode header
291 # Minimal test checking for header version and loader version as 1
292 #
293 movl $0x01, %eax
294 cmpl %eax, UcodeHdrVersion(%esi) #cmp [esi].ucode_hdr.version, eax
295 jne AdvanceFixedSize
296 cmpl %eax, UcodeHdrLoader(%esi) #cmp [esi].ucode_hdr.loader, eax
297 jne AdvanceFixedSize
298
299 #
300 # Check if signature and plaform ID match
301 #
302 cmpl UcodeHdrProcessor(%esi), %ebx #cmp ebx, [esi].ucode_hdr.processor
303 jne LoadUcodeL0
304 testl UcodeHdrFlags(%esi), %edx #test edx, [esi].ucode_hdr.flags
305 jnz LoadCheck #Jif signature and platform ID match
306
307 LoadUcodeL0:
308 #
309 # Check if extended header exists
310 # First check if total_size and data_size are valid
311 #
312 xorl %eax, %eax
313 cmpl %eax, UcodeHdrTotalSize(%esi) #cmp [esi].ucode_hdr.total_size, eax
314 je NextMicrocode
315 cmpl %eax, UcodeHdrDataSize(%esi) #cmp [esi].ucode_hdr.data_size, eax
316 je NextMicrocode
317
318 #
319 # Then verify total size - sizeof header > data size
320 #
321 movl UcodeHdrTotalSize(%esi), %ecx #mov ecx, [esi].ucode_hdr.total_size
322 subl $UcodeHdrLength, %ecx #sub ecx, sizeof ucode_hdr
323 cmpl UcodeHdrDataSize(%esi), %ecx #cmp ecx, [esi].ucode_hdr.data_size
324 jle NextMicrocode
325
326 #
327 # Set edi -> extended header
328 #
329 movl %esi, %edi
330 addl $UcodeHdrLength, %edi #add edi, sizeof ucode_hdr
331 addl UcodeHdrDataSize(%esi), %edi #add edi, [esi].ucode_hdr.data_size
332
333 #
334 # Get count of extended structures
335 #
336 movl ExtSigHdrCount(%edi), %ecx #mov ecx, [edi].ext_sig_hdr.count
337
338 #
339 # Move pointer to first signature structure
340 #
341 addl ExtSigHdrLength, %edi #add edi, sizeof ext_sig_hdr
342
343 CheckExtSig:
344 #
345 # Check if extended signature and platform ID match
346 #
347 cmpl %ebx, ExtSigProcessor(%edi) #cmp [edi].ext_sig.processor, ebx
348 jne LoadUcodeL1
349 test %edx, ExtSigFlags(%edi) #test [edi].ext_sig.flags, edx
350 jnz LoadCheck # Jif signature and platform ID match
351 LoadUcodeL1:
352 #
353 # Check if any more extended signatures exist
354 #
355 addl $ExtSigLength, %edi #add edi, sizeof ext_sig
356 loop CheckExtSig
357
358 NextMicrocode:
359 #
360 # Advance just after end of this microcode
361 #
362 xorl %eax, %eax
363 cmpl %eax, UcodeHdrTotalSize(%esi) #cmp [esi].ucode_hdr.total_size, eax
364 je LoadUcodeL2
365 addl UcodeHdrTotalSize(%esi), %esi #add esi, [esi].ucode_hdr.total_size
366 jmp CheckAddress
367 LoadUcodeL2:
368 addl $0x800, %esi #add esi, dword ptr 2048
369 jmp CheckAddress
370
371 AdvanceFixedSize:
372 #
373 # Advance by 4X dwords
374 #
375 addl $0x400, %esi #add esi, dword ptr 1024
376
377 CheckAddress:
378 #
379 # Is valid Microcode start point ?
380 #
381 cmpl $0x0ffffffff, UcodeHdrVersion(%esi)
382
383 #
384 # Is automatic size detection ?
385 #
386 movl LoadUcodeParamsUcodeCodeSize(%esp), %eax
387 cmpl $0x0ffffffff, %eax
388 jz LoadUcodeL3
389 #
390 # Address >= microcode region address + microcode region size?
391 #
392 addl LoadUcodeParamsUcodeCodeAddr(%esp), %eax #mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr
393
394 cmpl %eax, %esi
395 jae Done #Jif address is outside of ucode region
396 jmp CheckMainHeader
397
398 LoadUcodeL3:
399 LoadCheck:
400 #
401 # Get the revision of the current microcode update loaded
402 #
403 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
404 xorl %eax, %eax # Clear EAX
405 xorl %edx, %edx # Clear EDX
406 wrmsr # Load 0 to MSR at 8Bh
407
408 movl $0x01, %eax
409 cpuid
410 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
411 rdmsr # Get current microcode signature
412
413 #
414 # Verify this microcode update is not already loaded
415 #
416 cmpl %edx, UcodeHdrRevision(%esi) #cmp [esi].ucode_hdr.revision, edx
417 je Continue
418
419 LoadMicrocode:
420 #
421 # EAX contains the linear address of the start of the Update Data
422 # EDX contains zero
423 # ECX contains 79h (IA32_BIOS_UPDT_TRIG)
424 # Start microcode load with wrmsr
425 #
426 movl %esi, %eax
427 addl $UcodeHdrLength, %eax #add eax, sizeof ucode_hdr
428 xorl %edx, %edx
429 movl $MSR_IA32_BIOS_UPDT_TRIG, %ecx
430 wrmsr
431 movl $0x01, %eax
432 cpuid
433
434 Continue:
435 jmp NextMicrocode
436
437 Done:
438 movl $0x01, %eax
439 cpuid
440 movl $MSR_IA32_BIOS_SIGN_ID, %ecx
441 rdmsr # Get current microcode signature
442 xorl %eax, %eax
443 cmpl $0x00, %edx
444 jnz LoadUcodeExit
445 movl $0x08000000E, %eax
446
447 LoadUcodeExit:
448 jmp *%ebp
449
450
451 #----------------------------------------------------------------------------
452 # TempRamInit API
453 #
454 # This FSP API will load the microcode update, enable code caching for the
455 # region specified by the boot loader and also setup a temporary stack to be
456 # used till main memory is initialized.
457 #
458 #----------------------------------------------------------------------------
459 ASM_GLOBAL ASM_PFX(TempRamInitApi)
460 ASM_PFX(TempRamInitApi):
461 #
462 # Ensure SSE is enabled
463 #
464 ENABLE_SSE
465
466 #
467 # Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
468 #
469 SAVE_REGS
470
471 #
472 # Save timestamp into XMM4 & XMM5
473 #
474 rdtsc
475 SAVE_EAX
476 SAVE_EDX
477
478 #
479 # Check Parameter
480 #
481 movl 4(%esp), %eax
482 cmpl $0x00, %eax
483 movl $0x80000002, %eax
484 jz NemInitExit
485
486 #
487 # CPUID/DeviceID check
488 #
489 movl $TempRamInitApiL0, %eax
490 jmp ASM_PFX(FspSelfCheckDflt) # Note: ESP can not be changed.
491 TempRamInitApiL0:
492 cmpl $0x00, %eax
493 jnz NemInitExit
494
495 #
496 # Platform Basic Init.
497 #
498 movl $TempRamInitApiL1, %eax
499 jmp ASM_PFX(PlatformBasicInitDflt)
500 TempRamInitApiL1:
501 cmpl $0x00, %eax
502 jnz NemInitExit
503
504 #
505 # Load microcode
506 #
507 movl $TempRamInitApiL2, %eax
508 addl $0x04, %esp
509 jmp LoadUcode
510
511 TempRamInitApiL2:
512 LOAD_ESP
513 cmpl $0x00, %eax
514 jnz NemInitExit
515
516 #
517 # Call platform NEM init
518 #
519 movl $TempRamInitApiL3, %eax
520 addl $0x04, %esp
521 jmp ASM_PFX(PlatformTempRamInit)
522 TempRamInitApiL3:
523 subl $0x04, %esp
524 cmpl $0x00, %eax
525 jnz NemInitExit
526
527 #
528 # Save parameter pointer in edx
529 #
530 movl 4(%esp), %edx
531
532 #
533 # Enable FSP STACK
534 #
535 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp
536 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %esp
537
538 pushl $DATA_LEN_OF_MCUD # Size of the data region
539 pushl $0x4455434D # Signature of the data region 'MCUD'
540 pushl 4(%edx) # Microcode size
541 pushl (%edx) # Microcode base
542 pushl 12(%edx) # Code size
543 pushl 8(%edx) # Code base
544
545 #
546 # Save API entry/exit timestamp into stack
547 #
548 pushl $DATA_LEN_OF_PER0 # Size of the data region
549 pushl $0x30524550 # Signature of the data region 'PER0'
550 rdtsc
551 pushl %edx
552 pushl %eax
553 LOAD_EAX
554 LOAD_EDX
555 pushl %edx
556 pushl %eax
557
558 #
559 # Terminator for the data on stack
560 #
561 pushl $0x00
562
563 #
564 # Set ECX/EDX to the bootloader temporary memory range
565 #
566 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %ecx
567 movl %ecx, %edx
568 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %edx
569 subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %edx
570
571 xorl %eax, %eax
572
573 NemInitExit:
574 #
575 # Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
576 #
577 LOAD_REGS
578 ret
579
580
581 #----------------------------------------------------------------------------
582 # FspInit API
583 #
584 # This FSP API will perform the processor and chipset initialization.
585 # This API will not return. Instead, it transfers the control to the
586 # ContinuationFunc provided in the parameter.
587 #
588 #----------------------------------------------------------------------------
589 ASM_GLOBAL ASM_PFX(FspInitApi)
590 ASM_PFX(FspInitApi):
591 #
592 # Stack must be ready
593 #
594 pushl $0x087654321
595 popl %eax
596 cmpl $0x087654321, %eax
597 jz FspInitApiL0
598 movl $0x080000003, %eax
599 jmp FspInitApiexit
600
601 FspInitApiL0:
602 #
603 # Additional check
604 #
605 pusha
606 pushl $0x01
607 call ASM_PFX(FspApiCallingCheck)
608 addl $0x04, %esp
609 movl %eax, 28(%esp)
610 popa
611 cmpl $0x00, %eax
612 jz FspInitApiL1
613 jmp FspInitApiexit
614
615 FspInitApiL1:
616 #
617 # Store the address in FSP which will return control to the BL
618 #
619 pushl $FspInitApiexit
620
621 #
622 # Create a Task Frame in the stack for the Boot Loader
623 #
624 pushfl # 2 pushf for 4 byte alignment
625 cli
626 pushal
627
628 #
629 # Reserve 8 bytes for IDT save/restore
630 #
631 subl $0x08, %esp
632 sidt (%esp)
633
634 #
635 # Setup new FSP stack
636 #
637 movl %esp, %eax
638 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %esp
639 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %esp
640 subl $(DATA_LEN_AT_STACK_TOP + 0x40), %esp
641
642 # Save the bootloader's stack pointer
643 #
644 pushl %eax
645
646 #
647 # Pass entry point of the PEI core
648 #
649 call ASM_PFX(GetFspBaseAddress)
650 movl ASM_PFX(FspImageSizeOffset), %edi
651 movl (%eax, %edi), %edi
652 addl %eax, %edi
653 subl $0x20, %edi
654 addl (%edi), %eax
655 pushl %eax
656
657 #
658 # Pass BFV into the PEI Core
659 # It uses relative address to calucate the actual boot FV base
660 # For FSP impleantion with single FV, PcdFlashFvRecoveryBase and
661 # PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
662 # they are different. The code below can handle both cases.
663 #
664 call ASM_PFX(GetFspBaseAddress)
665 movl %eax , %edi
666 call ASM_PFX(GetBootFirmwareVolumeOffset)
667 addl %edi ,%eax
668 pushl %eax
669
670 #
671 # Pass stack base and size into the PEI Core
672 #
673 movl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamBase), %eax
674 addl ASM_PFX(_gPcd_FixedAtBuild_PcdTemporaryRamSize), %eax
675 subl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize), %eax
676 pushl %eax
677 pushl ASM_PFX(_gPcd_FixedAtBuild_PcdFspTemporaryRamSize)
678
679 #
680 # Pass Control into the PEI Core
681 #
682 call ASM_PFX(SecStartup)
683
684 FspInitApiexit:
685 ret
686
687
688 #----------------------------------------------------------------------------
689 # NotifyPhase API
690 #
691 # This FSP API will notify the FSP about the different phases in the boot
692 # process
693 #
694 #----------------------------------------------------------------------------
695 ASM_GLOBAL ASM_PFX(NotifyPhaseApi)
696 ASM_PFX(NotifyPhaseApi):
697 #
698 # Stack must be ready
699 #
700 pushl $0x0087654321
701 popl %eax
702 cmpl $0x087654321, %eax
703 jz NotifyPhaseApiL0
704 movl $0x080000003, %eax
705 jmp NotifyPhaseApiErrExit
706
707 NotifyPhaseApiL0:
708 #
709 # Verify the calling condition
710 #
711 pusha
712 pushl $0x02
713 call ASM_PFX(FspApiCallingCheck)
714 addl $0x04, %esp
715 movl %eax, 28(%esp)
716 popa
717
718 cmpl $0x00, %eax
719 jz NotifyPhaseApiL1
720
721 #
722 # Error return
723 #
724 NotifyPhaseApiErrExit:
725 ret
726
727 NotifyPhaseApiL1:
728 jmp ASM_PFX(Pei2LoaderSwitchStack)
729
730
731
732 #END