]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
DynamicTablesPkg: GTDT updates for ACPI 6.3
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.asm
1 ;; @file
2 ; Provide FSP API entry points.
3 ;
4 ; Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
5 ; SPDX-License-Identifier: BSD-2-Clause-Patent
6 ;;
7
8 .586p
9 .model flat,C
10 .code
11 .xmm
12
13 INCLUDE SaveRestoreSse.inc
14 INCLUDE MicrocodeLoad.inc
15
16 ;
17 ; Following are fixed PCDs
18 ;
19 EXTERN PcdGet32(PcdTemporaryRamBase):DWORD
20 EXTERN PcdGet32(PcdTemporaryRamSize):DWORD
21 EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD
22 EXTERN PcdGet32(PcdFspAreaSize):DWORD
23
24 ;
25 ; Following functions will be provided in C
26 ;
27
28 EXTERN SecStartup:PROC
29 EXTERN FspApiCallingCheck:PROC
30
31 ;
32 ; Following functions will be provided in PlatformSecLib
33 ;
34 EXTERN AsmGetFspBaseAddress:PROC
35 EXTERN AsmGetFspInfoHeader:PROC
36 EXTERN GetBootFirmwareVolumeOffset:PROC
37 EXTERN Loader2PeiSwitchStack:PROC
38 EXTERN LoadMicrocode(LoadMicrocodeDefault):PROC
39 EXTERN SecPlatformInit(SecPlatformInitDefault):PROC
40 EXTERN SecCarInit:PROC
41
42 ;
43 ; Define the data length that we saved on the stack top
44 ;
45 DATA_LEN_OF_PER0 EQU 18h
46 DATA_LEN_OF_MCUD EQU 18h
47 DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
48
49 ;
50 ; Define SSE macros
51 ;
52 LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister
53 mov esi, ReturnAddress
54 movd MmxRegister, esi ; save ReturnAddress into MMX
55 ENDM
56
57 CALL_MMX_EXT MACRO RoutineLabel, MmxRegister
58 local ReturnAddress
59 mov esi, offset ReturnAddress
60 movd MmxRegister, esi ; save ReturnAddress into MMX
61 jmp RoutineLabel
62 ReturnAddress:
63 ENDM
64
65 RET_ESI_EXT MACRO MmxRegister
66 movd esi, MmxRegister ; move ReturnAddress from MMX to ESI
67 jmp esi
68 ENDM
69
70 CALL_MMX MACRO RoutineLabel
71 CALL_MMX_EXT RoutineLabel, mm7
72 ENDM
73
74 RET_ESI MACRO
75 RET_ESI_EXT mm7
76 ENDM
77
78 ;------------------------------------------------------------------------------
79 SecPlatformInitDefault PROC NEAR PUBLIC
80 ; Inputs:
81 ; mm7 -> Return address
82 ; Outputs:
83 ; eax -> 0 - Successful, Non-zero - Failed.
84 ; Register Usage:
85 ; eax is cleared and ebp is used for return address.
86 ; All others reserved.
87
88 ; Save return address to EBP
89 movd ebp, mm7
90
91 xor eax, eax
92 exit:
93 jmp ebp
94 SecPlatformInitDefault ENDP
95
96 ;------------------------------------------------------------------------------
97 LoadMicrocodeDefault PROC NEAR PUBLIC
98 ; Inputs:
99 ; esp -> LoadMicrocodeParams pointer
100 ; Register Usage:
101 ; esp Preserved
102 ; All others destroyed
103 ; Assumptions:
104 ; No memory available, stack is hard-coded and used for return address
105 ; Executed by SBSP and NBSP
106 ; Beginning of microcode update region starts on paragraph boundary
107
108 ;
109 ;
110 ; Save return address to EBP
111 movd ebp, mm7
112
113 cmp esp, 0
114 jz paramerror
115 mov eax, dword ptr [esp + 4] ; Parameter pointer
116 cmp eax, 0
117 jz paramerror
118 mov esp, eax
119 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
120 cmp esi, 0
121 jnz check_main_header
122
123 paramerror:
124 mov eax, 080000002h
125 jmp exit
126
127 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
128
129 check_main_header:
130 ; Get processor signature and platform ID from the installed processor
131 ; and save into registers for later use
132 ; ebx = processor signature
133 ; edx = platform ID
134 mov eax, 1
135 cpuid
136 mov ebx, eax
137 mov ecx, MSR_IA32_PLATFORM_ID
138 rdmsr
139 mov ecx, edx
140 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
141 and ecx, 7h ; platform id at bit[52..50]
142 mov edx, 1
143 shl edx, cl
144
145 ; Current register usage
146 ; esp -> stack with paramters
147 ; esi -> microcode update to check
148 ; ebx = processor signature
149 ; edx = platform ID
150
151 ; Check for valid microcode header
152 ; Minimal test checking for header version and loader version as 1
153 mov eax, dword ptr 1
154 cmp [esi].MicrocodeHdr.MicrocodeHdrVersion, eax
155 jne advance_fixed_size
156 cmp [esi].MicrocodeHdr.MicrocodeHdrLoader, eax
157 jne advance_fixed_size
158
159 ; Check if signature and plaform ID match
160 cmp ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor
161 jne @f
162 test edx, [esi].MicrocodeHdr.MicrocodeHdrFlags
163 jnz load_check ; Jif signature and platform ID match
164
165 @@:
166 ; Check if extended header exists
167 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
168 xor eax, eax
169 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
170 je next_microcode
171 cmp [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax
172 je next_microcode
173
174 ; Then verify total size - sizeof header > data size
175 mov ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
176 sub ecx, sizeof MicrocodeHdr
177 cmp ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize
178 jng next_microcode ; Jif extended header does not exist
179
180 ; Set edi -> extended header
181 mov edi, esi
182 add edi, sizeof MicrocodeHdr
183 add edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize
184
185 ; Get count of extended structures
186 mov ecx, [edi].ExtSigHdr.ExtSigHdrCount
187
188 ; Move pointer to first signature structure
189 add edi, sizeof ExtSigHdr
190
191 check_ext_sig:
192 ; Check if extended signature and platform ID match
193 cmp [edi].ExtSig.ExtSigProcessor, ebx
194 jne @f
195 test [edi].ExtSig.ExtSigFlags, edx
196 jnz load_check ; Jif signature and platform ID match
197 @@:
198 ; Check if any more extended signatures exist
199 add edi, sizeof ExtSig
200 loop check_ext_sig
201
202 next_microcode:
203 ; Advance just after end of this microcode
204 xor eax, eax
205 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax
206 je @f
207 add esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize
208 jmp check_address
209 @@:
210 add esi, dword ptr 2048
211 jmp check_address
212
213 advance_fixed_size:
214 ; Advance by 4X dwords
215 add esi, dword ptr 1024
216
217 check_address:
218 ; Is valid Microcode start point ?
219 cmp dword ptr [esi].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh
220 jz done
221
222 ; Is automatic size detection ?
223 mov eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize
224 cmp eax, 0ffffffffh
225 jz @f
226
227 ; Address >= microcode region address + microcode region size?
228 add eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr
229 cmp esi, eax
230 jae done ;Jif address is outside of microcode region
231 jmp check_main_header
232
233 @@:
234 load_check:
235 ; Get the revision of the current microcode update loaded
236 mov ecx, MSR_IA32_BIOS_SIGN_ID
237 xor eax, eax ; Clear EAX
238 xor edx, edx ; Clear EDX
239 wrmsr ; Load 0 to MSR at 8Bh
240
241 mov eax, 1
242 cpuid
243 mov ecx, MSR_IA32_BIOS_SIGN_ID
244 rdmsr ; Get current microcode signature
245
246 ; Verify this microcode update is not already loaded
247 cmp [esi].MicrocodeHdr.MicrocodeHdrRevision, edx
248 je continue
249
250 load_microcode:
251 ; EAX contains the linear address of the start of the Update Data
252 ; EDX contains zero
253 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
254 ; Start microcode load with wrmsr
255 mov eax, esi
256 add eax, sizeof MicrocodeHdr
257 xor edx, edx
258 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
259 wrmsr
260 mov eax, 1
261 cpuid
262
263 continue:
264 jmp next_microcode
265
266 done:
267 mov eax, 1
268 cpuid
269 mov ecx, MSR_IA32_BIOS_SIGN_ID
270 rdmsr ; Get current microcode signature
271 xor eax, eax
272 cmp edx, 0
273 jnz exit
274 mov eax, 08000000Eh
275
276 exit:
277 jmp ebp
278
279 LoadMicrocodeDefault ENDP
280
281 EstablishStackFsp PROC NEAR PRIVATE
282 ;
283 ; Save parameter pointer in edx
284 ;
285 mov edx, dword ptr [esp + 4]
286
287 ;
288 ; Enable FSP STACK
289 ;
290 mov esp, PcdGet32 (PcdTemporaryRamBase)
291 add esp, PcdGet32 (PcdTemporaryRamSize)
292
293 push DATA_LEN_OF_MCUD ; Size of the data region
294 push 4455434Dh ; Signature of the data region 'MCUD'
295 push dword ptr [edx + 12] ; Code size
296 push dword ptr [edx + 8] ; Code base
297 push dword ptr [edx + 4] ; Microcode size
298 push dword ptr [edx] ; Microcode base
299
300 ;
301 ; Save API entry/exit timestamp into stack
302 ;
303 push DATA_LEN_OF_PER0 ; Size of the data region
304 push 30524550h ; Signature of the data region 'PER0'
305 LOAD_EDX
306 push edx
307 LOAD_EAX
308 push eax
309 rdtsc
310 push edx
311 push eax
312
313 ;
314 ; Terminator for the data on stack
315 ;
316 push 0
317
318 ;
319 ; Set ECX/EDX to the BootLoader temporary memory range
320 ;
321 mov ecx, PcdGet32 (PcdTemporaryRamBase)
322 mov edx, ecx
323 add edx, PcdGet32 (PcdTemporaryRamSize)
324 sub edx, PcdGet32 (PcdFspTemporaryRamSize)
325
326 xor eax, eax
327
328 RET_ESI
329
330 EstablishStackFsp ENDP
331
332
333 ;----------------------------------------------------------------------------
334 ; TempRamInit API
335 ;
336 ; This FSP API will load the microcode update, enable code caching for the
337 ; region specified by the boot loader and also setup a temporary stack to be
338 ; used till main memory is initialized.
339 ;
340 ;----------------------------------------------------------------------------
341 TempRamInitApi PROC NEAR PUBLIC
342 ;
343 ; Ensure SSE is enabled
344 ;
345 ENABLE_SSE
346
347 ;
348 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
349 ;
350 SAVE_REGS
351
352 ;
353 ; Save timestamp into XMM6
354 ;
355 rdtsc
356 SAVE_EAX
357 SAVE_EDX
358
359 ;
360 ; Check Parameter
361 ;
362 mov eax, dword ptr [esp + 4]
363 cmp eax, 0
364 mov eax, 80000002h
365 jz TempRamInitExit
366
367 ;
368 ; Sec Platform Init
369 ;
370 CALL_MMX SecPlatformInit
371 cmp eax, 0
372 jnz TempRamInitExit
373
374 ; Load microcode
375 LOAD_ESP
376 CALL_MMX LoadMicrocode
377 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
378 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
379
380 ; Call Sec CAR Init
381 LOAD_ESP
382 CALL_MMX SecCarInit
383 cmp eax, 0
384 jnz TempRamInitExit
385
386 LOAD_ESP
387 CALL_MMX EstablishStackFsp
388
389 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
390
391 TempRamInitExit:
392 ;
393 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
394 ;
395 LOAD_REGS
396 ret
397 TempRamInitApi ENDP
398
399 ;----------------------------------------------------------------------------
400 ; FspInit API
401 ;
402 ; This FSP API will perform the processor and chipset initialization.
403 ; This API will not return. Instead, it transfers the control to the
404 ; ContinuationFunc provided in the parameter.
405 ;
406 ;----------------------------------------------------------------------------
407 FspInitApi PROC NEAR PUBLIC
408 mov eax, 1
409 jmp FspApiCommon
410 FspInitApi ENDP
411
412 ;----------------------------------------------------------------------------
413 ; NotifyPhase API
414 ;
415 ; This FSP API will notify the FSP about the different phases in the boot
416 ; process
417 ;
418 ;----------------------------------------------------------------------------
419 NotifyPhaseApi PROC C PUBLIC
420 mov eax, 2
421 jmp FspApiCommon
422 NotifyPhaseApi ENDP
423
424 ;----------------------------------------------------------------------------
425 ; FspMemoryInit API
426 ;
427 ; This FSP API is called after TempRamInit and initializes the memory.
428 ;
429 ;----------------------------------------------------------------------------
430 FspMemoryInitApi PROC NEAR PUBLIC
431 mov eax, 3
432 jmp FspApiCommon
433 FspMemoryInitApi ENDP
434
435
436 ;----------------------------------------------------------------------------
437 ; TempRamExitApi API
438 ;
439 ; This API tears down temporary RAM
440 ;
441 ;----------------------------------------------------------------------------
442 TempRamExitApi PROC C PUBLIC
443 mov eax, 4
444 jmp FspApiCommon
445 TempRamExitApi ENDP
446
447
448 ;----------------------------------------------------------------------------
449 ; FspSiliconInit API
450 ;
451 ; This FSP API initializes the CPU and the chipset including the IO
452 ; controllers in the chipset to enable normal operation of these devices.
453 ;
454 ;----------------------------------------------------------------------------
455 FspSiliconInitApi PROC C PUBLIC
456 mov eax, 5
457 jmp FspApiCommon
458 FspSiliconInitApi ENDP
459
460 ;----------------------------------------------------------------------------
461 ; FspApiCommon API
462 ;
463 ; This is the FSP API common entry point to resume the FSP execution
464 ;
465 ;----------------------------------------------------------------------------
466 FspApiCommon PROC C PUBLIC
467 ;
468 ; EAX holds the API index
469 ;
470
471 ;
472 ; Stack must be ready
473 ;
474 push eax
475 add esp, 4
476 cmp eax, dword ptr [esp - 4]
477 jz @F
478 mov eax, 080000003h
479 jmp exit
480
481 @@:
482 ;
483 ; Verify the calling condition
484 ;
485 pushad
486 push [esp + 4 * 8 + 4] ; push ApiParam
487 push eax ; push ApiIdx
488 call FspApiCallingCheck
489 add esp, 8
490 cmp eax, 0
491 jz @F
492 mov dword ptr [esp + 4 * 7], eax
493 popad
494 ret
495
496 @@:
497 popad
498 cmp eax, 1 ; FspInit API
499 jz @F
500 cmp eax, 3 ; FspMemoryInit API
501 jz @F
502
503 call AsmGetFspInfoHeader
504 jmp Loader2PeiSwitchStack
505
506 @@:
507 ;
508 ; FspInit and FspMemoryInit APIs, setup the initial stack frame
509 ;
510
511 ;
512 ; Place holder to store the FspInfoHeader pointer
513 ;
514 push eax
515
516 ;
517 ; Update the FspInfoHeader pointer
518 ;
519 push eax
520 call AsmGetFspInfoHeader
521 mov [esp + 4], eax
522 pop eax
523
524 ;
525 ; Create a Task Frame in the stack for the Boot Loader
526 ;
527 pushfd ; 2 pushf for 4 byte alignment
528 cli
529 pushad
530
531 ; Reserve 8 bytes for IDT save/restore
532 sub esp, 8
533 sidt fword ptr [esp]
534
535 ;
536 ; Setup new FSP stack
537 ;
538 mov edi, esp
539 mov esp, PcdGet32(PcdTemporaryRamBase)
540 add esp, PcdGet32(PcdTemporaryRamSize)
541 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)
542
543 ;
544 ; Pass the API Idx to SecStartup
545 ;
546 push eax
547
548 ;
549 ; Pass the BootLoader stack to SecStartup
550 ;
551 push edi
552
553 ;
554 ; Pass entry point of the PEI core
555 ;
556 call AsmGetFspBaseAddress
557 mov edi, eax
558 add edi, PcdGet32 (PcdFspAreaSize)
559 sub edi, 20h
560 add eax, DWORD PTR ds:[edi]
561 push eax
562
563 ;
564 ; Pass BFV into the PEI Core
565 ; It uses relative address to calucate the actual boot FV base
566 ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and
567 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,
568 ; they are different. The code below can handle both cases.
569 ;
570 call AsmGetFspBaseAddress
571 mov edi, eax
572 call GetBootFirmwareVolumeOffset
573 add eax, edi
574 push eax
575
576 ;
577 ; Pass stack base and size into the PEI Core
578 ;
579 mov eax, PcdGet32(PcdTemporaryRamBase)
580 add eax, PcdGet32(PcdTemporaryRamSize)
581 sub eax, PcdGet32(PcdFspTemporaryRamSize)
582 push eax
583 push PcdGet32(PcdFspTemporaryRamSize)
584
585 ;
586 ; Pass Control into the PEI Core
587 ;
588 call SecStartup
589 add esp, 4
590 exit:
591 ret
592
593 FspApiCommon ENDP
594
595 END