]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
7fd3d6d84315746e6ff12c4fd818a8acb9f04d2a
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / Ia32 / FspApiEntryT.nasm
1 ;; @file
2 ; Provide FSP API entry points.
3 ;
4 ; Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
5 ; SPDX-License-Identifier: BSD-2-Clause-Patent
6 ;;
7
8 SECTION .text
9
10 %include "SaveRestoreSseNasm.inc"
11 %include "MicrocodeLoadNasm.inc"
12
13 ;
14 ; Following are fixed PCDs
15 ;
16 extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
17 extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
18 extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
19
20 ;
21 ; Following functions will be provided in PlatformSecLib
22 ;
23 extern ASM_PFX(AsmGetFspBaseAddress)
24 extern ASM_PFX(AsmGetFspInfoHeader)
25 ;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation
26 extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation
27 extern ASM_PFX(SecCarInit)
28
29 ;
30 ; Define the data length that we saved on the stack top
31 ;
32 DATA_LEN_OF_PER0 EQU 18h
33 DATA_LEN_OF_MCUD EQU 18h
34 DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)
35
36 ;
37 ; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid
38 ; build error. This needs to be fixed later on.
39 ;
40 struc MicrocodeHdr
41 .MicrocodeHdrVersion: resd 1
42 .MicrocodeHdrRevision: resd 1
43 .MicrocodeHdrDate: resd 1
44 .MicrocodeHdrProcessor: resd 1
45 .MicrocodeHdrChecksum: resd 1
46 .MicrocodeHdrLoader: resd 1
47 .MicrocodeHdrFlags: resd 1
48 .MicrocodeHdrDataSize: resd 1
49 .MicrocodeHdrTotalSize: resd 1
50 .MicrocodeHdrRsvd: resd 3
51 .size:
52 endstruc
53
54 struc ExtSigHdr
55 .ExtSigHdrCount: resd 1
56 .ExtSigHdrChecksum: resd 1
57 .ExtSigHdrRsvd: resd 3
58 .size:
59 endstruc
60
61 struc ExtSig
62 .ExtSigProcessor: resd 1
63 .ExtSigFlags: resd 1
64 .ExtSigChecksum: resd 1
65 .size:
66 endstruc
67
68 struc LoadMicrocodeParams
69 ; FSP_UPD_HEADER {
70 .FspUpdHeader: resd 8
71 ; }
72 ; FSPT_CORE_UPD {
73 .MicrocodeCodeAddr: resd 1
74 .MicrocodeCodeSize: resd 1
75 .CodeRegionBase: resd 1
76 .CodeRegionSize: resd 1
77 ; }
78 .size:
79 endstruc
80
81 struc LoadMicrocodeParamsFsp22
82 ; FSP_UPD_HEADER {
83 .FspUpdHeaderSignature: resd 2
84 .FspUpdHeaderRevision: resb 1
85 .FspUpdHeaderReserved: resb 23
86 ; }
87 ; FSPT_ARCH_UPD{
88 .FsptArchUpd: resd 8
89 ; }
90 ; FSPT_CORE_UPD {
91 .MicrocodeCodeAddr: resd 1
92 .MicrocodeCodeSize: resd 1
93 .CodeRegionBase: resd 1
94 .CodeRegionSize: resd 1
95 ; }
96 .size:
97 endstruc
98
99 ;
100 ; Define SSE macros
101 ;
102 ;
103 ;args 1: ReturnAddress 2:MmxRegister
104 ;
105 %macro LOAD_MMX_EXT 2
106 mov esi, %1
107 movd %2, esi ; save ReturnAddress into MMX
108 %endmacro
109
110 ;
111 ;args 1: RoutineLabel 2:MmxRegister
112 ;
113 %macro CALL_MMX_EXT 2
114 mov esi, %%ReturnAddress
115 movd %2, esi ; save ReturnAddress into MMX
116 jmp %1
117 %%ReturnAddress:
118 %endmacro
119
120 ;
121 ;arg 1:MmxRegister
122 ;
123 %macro RET_ESI_EXT 1
124 movd esi, %1 ; move ReturnAddress from MMX to ESI
125 jmp esi
126 %endmacro
127
128 ;
129 ;arg 1:RoutineLabel
130 ;
131 %macro CALL_MMX 1
132 CALL_MMX_EXT %1, mm7
133 %endmacro
134
135 %macro RET_ESI 0
136 RET_ESI_EXT mm7
137 %endmacro
138
139 ;
140 ; @todo: The strong/weak implementation does not work.
141 ; This needs to be reviewed later.
142 ;
143 ;------------------------------------------------------------------------------
144 ;
145 ;;global ASM_PFX(SecPlatformInitDefault)
146 ;ASM_PFX(SecPlatformInitDefault):
147 ; ; Inputs:
148 ; ; mm7 -> Return address
149 ; ; Outputs:
150 ; ; eax -> 0 - Successful, Non-zero - Failed.
151 ; ; Register Usage:
152 ; ; eax is cleared and ebp is used for return address.
153 ; ; All others reserved.
154 ;
155 ; ; Save return address to EBP
156 ; movd ebp, mm7
157 ;
158 ; xor eax, eax
159 ;Exit1:
160 ; jmp ebp
161
162 ;------------------------------------------------------------------------------
163 global ASM_PFX(LoadMicrocodeDefault)
164 ASM_PFX(LoadMicrocodeDefault):
165 ; Inputs:
166 ; esp -> LoadMicrocodeParams pointer
167 ; Register Usage:
168 ; esp Preserved
169 ; All others destroyed
170 ; Assumptions:
171 ; No memory available, stack is hard-coded and used for return address
172 ; Executed by SBSP and NBSP
173 ; Beginning of microcode update region starts on paragraph boundary
174
175 ;
176 ;
177 ; Save return address to EBP
178 movd ebp, mm7
179
180 cmp esp, 0
181 jz ParamError
182 mov eax, dword [esp + 4] ; Parameter pointer
183 cmp eax, 0
184 jz ParamError
185 mov esp, eax
186
187 ; skip loading Microcode if the MicrocodeCodeSize is zero
188 ; and report error if size is less than 2k
189 ; first check UPD header revision
190 cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
191 jae Fsp22UpdHeader
192
193 ; UPD structure is compliant with FSP spec 2.0/2.1
194 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
195 cmp eax, 0
196 jz Exit2
197 cmp eax, 0800h
198 jl ParamError
199
200 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
201 cmp esi, 0
202 jnz CheckMainHeader
203 jmp ParamError
204
205 Fsp22UpdHeader:
206 ; UPD structure is compliant with FSP spec 2.2
207 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
208 cmp eax, 0
209 jz Exit2
210 cmp eax, 0800h
211 jl ParamError
212
213 mov esi, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
214 cmp esi, 0
215 jnz CheckMainHeader
216
217 ParamError:
218 mov eax, 080000002h
219 jmp Exit2
220
221 CheckMainHeader:
222 ; Get processor signature and platform ID from the installed processor
223 ; and save into registers for later use
224 ; ebx = processor signature
225 ; edx = platform ID
226 mov eax, 1
227 cpuid
228 mov ebx, eax
229 mov ecx, MSR_IA32_PLATFORM_ID
230 rdmsr
231 mov ecx, edx
232 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
233 and ecx, 7h ; platform id at bit[52..50]
234 mov edx, 1
235 shl edx, cl
236
237 ; Current register usage
238 ; esp -> stack with parameters
239 ; esi -> microcode update to check
240 ; ebx = processor signature
241 ; edx = platform ID
242
243 ; Check for valid microcode header
244 ; Minimal test checking for header version and loader version as 1
245 mov eax, dword 1
246 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
247 jne AdvanceFixedSize
248 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
249 jne AdvanceFixedSize
250
251 ; Check if signature and plaform ID match
252 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
253 jne LoadMicrocodeDefault1
254 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
255 jnz LoadCheck ; Jif signature and platform ID match
256
257 LoadMicrocodeDefault1:
258 ; Check if extended header exists
259 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
260 xor eax, eax
261 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
262 je NextMicrocode
263 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
264 je NextMicrocode
265
266 ; Then verify total size - sizeof header > data size
267 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
268 sub ecx, MicrocodeHdr.size
269 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
270 jng NextMicrocode ; Jif extended header does not exist
271
272 ; Set edi -> extended header
273 mov edi, esi
274 add edi, MicrocodeHdr.size
275 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
276
277 ; Get count of extended structures
278 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
279
280 ; Move pointer to first signature structure
281 add edi, ExtSigHdr.size
282
283 CheckExtSig:
284 ; Check if extended signature and platform ID match
285 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
286 jne LoadMicrocodeDefault2
287 test dword [edi + ExtSig.ExtSigFlags], edx
288 jnz LoadCheck ; Jif signature and platform ID match
289 LoadMicrocodeDefault2:
290 ; Check if any more extended signatures exist
291 add edi, ExtSig.size
292 loop CheckExtSig
293
294 NextMicrocode:
295 ; Advance just after end of this microcode
296 xor eax, eax
297 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
298 je LoadMicrocodeDefault3
299 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
300 jmp CheckAddress
301 LoadMicrocodeDefault3:
302 add esi, dword 2048
303 jmp CheckAddress
304
305 AdvanceFixedSize:
306 ; Advance by 4X dwords
307 add esi, dword 1024
308
309 CheckAddress:
310 ; Check UPD header revision
311 cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
312 jae Fsp22UpdHeader1
313
314 ; UPD structure is compliant with FSP spec 2.0/2.1
315 ; Is automatic size detection ?
316 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
317 cmp eax, 0ffffffffh
318 jz LoadMicrocodeDefault4
319
320 ; Address >= microcode region address + microcode region size?
321 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
322 cmp esi, eax
323 jae Done ;Jif address is outside of microcode region
324 jmp CheckMainHeader
325
326 Fsp22UpdHeader1:
327 ; UPD structure is compliant with FSP spec 2.2
328 ; Is automatic size detection ?
329 mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
330 cmp eax, 0ffffffffh
331 jz LoadMicrocodeDefault4
332
333 ; Address >= microcode region address + microcode region size?
334 add eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
335 cmp esi, eax
336 jae Done ;Jif address is outside of microcode region
337 jmp CheckMainHeader
338
339 LoadMicrocodeDefault4:
340 ; Is valid Microcode start point ?
341 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
342 jz Done
343
344 LoadCheck:
345 ; Get the revision of the current microcode update loaded
346 mov ecx, MSR_IA32_BIOS_SIGN_ID
347 xor eax, eax ; Clear EAX
348 xor edx, edx ; Clear EDX
349 wrmsr ; Load 0 to MSR at 8Bh
350
351 mov eax, 1
352 cpuid
353 mov ecx, MSR_IA32_BIOS_SIGN_ID
354 rdmsr ; Get current microcode signature
355
356 ; Verify this microcode update is not already loaded
357 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
358 je Continue
359
360 LoadMicrocode:
361 ; EAX contains the linear address of the start of the Update Data
362 ; EDX contains zero
363 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
364 ; Start microcode load with wrmsr
365 mov eax, esi
366 add eax, MicrocodeHdr.size
367 xor edx, edx
368 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
369 wrmsr
370 mov eax, 1
371 cpuid
372
373 Continue:
374 jmp NextMicrocode
375
376 Done:
377 mov eax, 1
378 cpuid
379 mov ecx, MSR_IA32_BIOS_SIGN_ID
380 rdmsr ; Get current microcode signature
381 xor eax, eax
382 cmp edx, 0
383 jnz Exit2
384 mov eax, 08000000Eh
385
386 Exit2:
387 jmp ebp
388
389
390 global ASM_PFX(EstablishStackFsp)
391 ASM_PFX(EstablishStackFsp):
392 ;
393 ; Save parameter pointer in edx
394 ;
395 mov edx, dword [esp + 4]
396
397 ;
398 ; Enable FSP STACK
399 ;
400 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
401 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
402
403 push DATA_LEN_OF_MCUD ; Size of the data region
404 push 4455434Dh ; Signature of the data region 'MCUD'
405
406 ; check UPD structure revision (edx + 8)
407 cmp byte [edx + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
408 jae Fsp22UpdHeader2
409
410 ; UPD structure is compliant with FSP spec 2.0/2.1
411 push dword [edx + LoadMicrocodeParams.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
412 push dword [edx + LoadMicrocodeParams.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
413 push dword [edx + LoadMicrocodeParams.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
414 push dword [edx + LoadMicrocodeParams.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
415 jmp ContinueAfterUpdPush
416
417 Fsp22UpdHeader2:
418 ; UPD structure is compliant with FSP spec 2.2
419 push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
420 push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
421 push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
422 push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
423
424 ContinueAfterUpdPush:
425 ;
426 ; Save API entry/exit timestamp into stack
427 ;
428 push DATA_LEN_OF_PER0 ; Size of the data region
429 push 30524550h ; Signature of the data region 'PER0'
430 rdtsc
431 push edx
432 push eax
433 LOAD_EDX
434 push edx
435 LOAD_EAX
436 push eax
437
438 ;
439 ; Terminator for the data on stack
440 ;
441 push 0
442
443 ;
444 ; Set ECX/EDX to the BootLoader temporary memory range
445 ;
446 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]
447 mov edx, ecx
448 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]
449 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]
450
451 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
452 jb EstablishStackFspSuccess
453 mov eax, 80000003h ;EFI_UNSUPPORTED
454 jmp EstablishStackFspExit
455 EstablishStackFspSuccess:
456 xor eax, eax
457
458 EstablishStackFspExit:
459 RET_ESI
460
461 ;----------------------------------------------------------------------------
462 ; TempRamInit API
463 ;
464 ; This FSP API will load the microcode update, enable code caching for the
465 ; region specified by the boot loader and also setup a temporary stack to be
466 ; used till main memory is initialized.
467 ;
468 ;----------------------------------------------------------------------------
469 global ASM_PFX(TempRamInitApi)
470 ASM_PFX(TempRamInitApi):
471 ;
472 ; Ensure SSE is enabled
473 ;
474 ENABLE_SSE
475
476 ;
477 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6
478 ;
479 SAVE_REGS
480
481 ;
482 ; Save timestamp into XMM6
483 ;
484 rdtsc
485 SAVE_EAX
486 SAVE_EDX
487
488 ;
489 ; Check Parameter
490 ;
491 mov eax, dword [esp + 4]
492 cmp eax, 0
493 mov eax, 80000002h
494 jz TempRamInitExit
495
496 ;
497 ; Sec Platform Init
498 ;
499 CALL_MMX ASM_PFX(SecPlatformInit)
500 cmp eax, 0
501 jnz TempRamInitExit
502
503 ; Load microcode
504 LOAD_ESP
505 CALL_MMX ASM_PFX(LoadMicrocodeDefault)
506 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.
507 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.
508
509 ; Call Sec CAR Init
510 LOAD_ESP
511 CALL_MMX ASM_PFX(SecCarInit)
512 cmp eax, 0
513 jnz TempRamInitExit
514
515 LOAD_ESP
516 CALL_MMX ASM_PFX(EstablishStackFsp)
517 cmp eax, 0
518 jnz TempRamInitExit
519
520 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.
521
522 TempRamInitExit:
523 mov bl, al ; save al data in bl
524 mov al, 07Fh ; API exit postcode 7f
525 out 080h, al
526 mov al, bl ; restore al data from bl
527
528 ;
529 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6
530 ;
531 LOAD_REGS
532 ret
533
534 ;----------------------------------------------------------------------------
535 ; Module Entrypoint API
536 ;----------------------------------------------------------------------------
537 global ASM_PFX(_ModuleEntryPoint)
538 ASM_PFX(_ModuleEntryPoint):
539 jmp $