]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm
a9f5f28ed70371555d57fdde66aef9eda8515df3
[mirror_edk2.git] / IntelFsp2Pkg / FspSecCore / X64 / FspApiEntryT.nasm
1 ;; @file
2 ; Provide FSP API entry points.
3 ;
4 ; Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
5 ; SPDX-License-Identifier: BSD-2-Clause-Patent
6 ;;
7
8 SECTION .text
9
10 %include "SaveRestoreSseAvxNasm.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 LoadMicrocodeParamsFsp24
69 ; FSP_UPD_HEADER {
70 .FspUpdHeaderSignature: resd 2
71 .FspUpdHeaderRevision: resb 1
72 .FspUpdHeaderReserved: resb 23
73 ; }
74 ; FSPT_ARCH2_UPD {
75 .FsptArchRevision: resb 1
76 .FsptArchReserved: resb 3
77 .FsptArchLength: resd 1
78 .FspDebugHandler resq 1
79 .FsptArchUpd: resd 4
80 ; }
81 ; FSPT_CORE_UPD {
82 .MicrocodeCodeAddr: resq 1
83 .MicrocodeCodeSize: resq 1
84 .CodeRegionBase: resq 1
85 .CodeRegionSize: resq 1
86 ; }
87 .size:
88 endstruc
89
90 ;
91 ; @todo: The strong/weak implementation does not work.
92 ; This needs to be reviewed later.
93 ;
94 ;------------------------------------------------------------------------------
95 ;
96 ;;global ASM_PFX(SecPlatformInitDefault)
97 ;ASM_PFX(SecPlatformInitDefault):
98 ; ; Inputs:
99 ; ; ymm7 -> Return address
100 ; ; Outputs:
101 ; ; rax -> 0 - Successful, Non-zero - Failed.
102 ; ; Register Usage:
103 ; ; rax is cleared and rbp is used for return address.
104 ; ; All others reserved.
105 ;
106 ; ; Save return address to RBP
107 ; LOAD_RBP
108 ;
109 ; xor rax, rax
110 ;Exit1:
111 ; jmp rbp
112
113 ;------------------------------------------------------------------------------
114 global ASM_PFX(LoadMicrocodeDefault)
115 ASM_PFX(LoadMicrocodeDefault):
116 ; Inputs:
117 ; rsp -> LoadMicrocodeParams pointer
118 ; Register Usage:
119 ; rsp Preserved
120 ; All others destroyed
121 ; Assumptions:
122 ; No memory available, stack is hard-coded and used for return address
123 ; Executed by SBSP and NBSP
124 ; Beginning of microcode update region starts on paragraph boundary
125
126 ;
127 ; Save return address to RBP
128 ;
129 LOAD_RBP
130
131 cmp rsp, 0
132 jz ParamError
133 mov eax, dword [rsp + 8] ; Parameter pointer
134 cmp eax, 0
135 jz ParamError
136 mov esp, eax
137
138 ; skip loading Microcode if the MicrocodeCodeSize is zero
139 ; and report error if size is less than 2k
140 ; first check UPD header revision
141 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
142 jb ParamError
143 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
144 jne ParamError
145
146 ; UPD structure is compliant with FSP spec 2.4
147 mov eax, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
148 cmp eax, 0
149 jz Exit2
150 cmp eax, 0800h
151 jl ParamError
152
153 mov esi, dword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
154 cmp esi, 0
155 jnz CheckMainHeader
156
157 ParamError:
158 mov rax, 08000000000000002h
159 jmp Exit2
160
161 CheckMainHeader:
162 ; Get processor signature and platform ID from the installed processor
163 ; and save into registers for later use
164 ; ebx = processor signature
165 ; edx = platform ID
166 mov eax, 1
167 cpuid
168 mov ebx, eax
169 mov ecx, MSR_IA32_PLATFORM_ID
170 rdmsr
171 mov ecx, edx
172 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
173 and ecx, 7h ; platform id at bit[52..50]
174 mov edx, 1
175 shl edx, cl
176
177 ; Current register usage
178 ; esp -> stack with parameters
179 ; esi -> microcode update to check
180 ; ebx = processor signature
181 ; edx = platform ID
182
183 ; Check for valid microcode header
184 ; Minimal test checking for header version and loader version as 1
185 mov eax, dword 1
186 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
187 jne AdvanceFixedSize
188 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
189 jne AdvanceFixedSize
190
191 ; Check if signature and plaform ID match
192 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
193 jne LoadMicrocodeDefault1
194 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
195 jnz LoadCheck ; Jif signature and platform ID match
196
197 LoadMicrocodeDefault1:
198 ; Check if extended header exists
199 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
200 xor rax, rax
201 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
202 je NextMicrocode
203 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
204 je NextMicrocode
205
206 ; Then verify total size - sizeof header > data size
207 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
208 sub ecx, MicrocodeHdr.size
209 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
210 jng NextMicrocode ; Jif extended header does not exist
211
212 ; Set edi -> extended header
213 mov edi, esi
214 add edi, MicrocodeHdr.size
215 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
216
217 ; Get count of extended structures
218 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
219
220 ; Move pointer to first signature structure
221 add edi, ExtSigHdr.size
222
223 CheckExtSig:
224 ; Check if extended signature and platform ID match
225 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
226 jne LoadMicrocodeDefault2
227 test dword [edi + ExtSig.ExtSigFlags], edx
228 jnz LoadCheck ; Jif signature and platform ID match
229 LoadMicrocodeDefault2:
230 ; Check if any more extended signatures exist
231 add edi, ExtSig.size
232 loop CheckExtSig
233
234 NextMicrocode:
235 ; Advance just after end of this microcode
236 xor rax, rax
237 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
238 je LoadMicrocodeDefault3
239 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
240 jmp CheckAddress
241 LoadMicrocodeDefault3:
242 add esi, dword 2048
243 jmp CheckAddress
244
245 AdvanceFixedSize:
246 ; Advance by 4X dwords
247 add esi, dword 1024
248
249 CheckAddress:
250 ; Check UPD header revision
251 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
252 jb ParamError
253 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
254 jne ParamError
255
256 ; UPD structure is compliant with FSP spec 2.4
257 ; Is automatic size detection ?
258 mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
259 cmp rax, 0ffffffffffffffffh
260 jz LoadMicrocodeDefault4
261
262 ; Address >= microcode region address + microcode region size?
263 add rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
264 cmp rsi, rax
265 jae Done ;Jif address is outside of microcode region
266 jmp CheckMainHeader
267
268 LoadMicrocodeDefault4:
269 ; Is valid Microcode start point ?
270 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
271 jz Done
272
273 LoadCheck:
274 ; Get the revision of the current microcode update loaded
275 mov ecx, MSR_IA32_BIOS_SIGN_ID
276 xor eax, eax ; Clear EAX
277 xor edx, edx ; Clear EDX
278 wrmsr ; Load 0 to MSR at 8Bh
279
280 mov eax, 1
281 cpuid
282 mov ecx, MSR_IA32_BIOS_SIGN_ID
283 rdmsr ; Get current microcode signature
284
285 ; Verify this microcode update is not already loaded
286 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx
287 je Continue
288
289 LoadMicrocode:
290 ; EAX contains the linear address of the start of the Update Data
291 ; EDX contains zero
292 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)
293 ; Start microcode load with wrmsr
294 mov eax, esi
295 add eax, MicrocodeHdr.size
296 xor edx, edx
297 mov ecx, MSR_IA32_BIOS_UPDT_TRIG
298 wrmsr
299 mov eax, 1
300 cpuid
301
302 Continue:
303 jmp NextMicrocode
304
305 Done:
306 mov eax, 1
307 cpuid
308 mov ecx, MSR_IA32_BIOS_SIGN_ID
309 rdmsr ; Get current microcode signature
310 xor eax, eax
311 cmp edx, 0
312 jnz Exit2
313 mov eax, 0800000000000000Eh
314
315 Exit2:
316 jmp rbp
317
318
319 global ASM_PFX(EstablishStackFsp)
320 ASM_PFX(EstablishStackFsp):
321 ;
322 ; Save parameter pointer in rdx
323 ;
324 mov rdx, qword [rsp + 8]
325
326 ;
327 ; Enable FSP STACK
328 ;
329 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
330 mov esp, DWORD[rax]
331 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
332 add esp, DWORD[rax]
333
334 sub esp, 4
335 mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region
336 sub esp, 4
337 mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'
338
339 ; check UPD structure revision (rdx + 8)
340 cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
341 jb ParamError1
342 cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
343 je Fsp24UpdHeader
344
345 ParamError1:
346 mov rax, 08000000000000002h
347 jmp EstablishStackFspExit
348
349 Fsp24UpdHeader:
350 ; UPD structure is compliant with FSP spec 2.4
351 xor rax, rax
352 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h
353 sub rsp, 8
354 mov qword[rsp], rax
355 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h
356 sub rsp, 8
357 mov qword[rsp], rax
358 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h
359 sub rsp, 8
360 mov qword[rsp], rax
361 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h
362 sub rsp, 8
363 mov qword[rsp], rax
364
365 ContinueAfterUpdPush:
366 ;
367 ; Save API entry/exit timestamp into stack
368 ;
369 sub esp, 4
370 mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region
371 sub esp, 4
372 mov dword[esp], 30524550h ; Signature of the data region 'PER0'
373 rdtsc
374 sub esp, 4
375 mov dword[esp], edx
376 sub esp, 4
377 mov dword[esp], eax
378 LOAD_TS rax
379 push rax
380
381 ;
382 ; Terminator for the data on stack
383 ;
384 push 0
385
386 ;
387 ; Set ECX/EDX to the BootLoader temporary memory range
388 ;
389 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
390 mov edx, [ecx]
391 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
392 add edx, [ecx]
393 mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
394 sub edx, [ecx]
395 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
396 mov ecx, [ecx]
397
398 cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
399 jb EstablishStackFspSuccess
400 mov rax, 08000000000000003h ; EFI_UNSUPPORTED
401 jmp EstablishStackFspExit
402 EstablishStackFspSuccess:
403 xor rax, rax
404
405 EstablishStackFspExit:
406 RET_YMM
407
408 ;----------------------------------------------------------------------------
409 ; TempRamInit API
410 ;
411 ; This FSP API will load the microcode update, enable code caching for the
412 ; region specified by the boot loader and also setup a temporary stack to be
413 ; used till main memory is initialized.
414 ;
415 ;----------------------------------------------------------------------------
416 global ASM_PFX(TempRamInitApi)
417 ASM_PFX(TempRamInitApi):
418 ;
419 ; Ensure both SSE and AVX are enabled
420 ;
421 ENABLE_SSE
422 ENABLE_AVX
423
424 ;
425 ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6
426 ;
427 SAVE_REGS
428
429 ;
430 ; Save BFV address in YMM9
431 ;
432 SAVE_BFV rbp
433
434 ;
435 ; Save timestamp into YMM6
436 ;
437 rdtsc
438 shl rdx, 32
439 or rax, rdx
440 SAVE_TS rax
441
442 ;
443 ; Check Parameter
444 ;
445 mov rax, qword [rsp + 8]
446 cmp rax, 0
447 mov rax, 08000000000000002h
448 jz TempRamInitExit
449
450 ;
451 ; Sec Platform Init
452 ;
453 CALL_YMM ASM_PFX(SecPlatformInit)
454 cmp eax, 0
455 jnz TempRamInitExit
456
457 ; Load microcode
458 LOAD_RSP
459 CALL_YMM ASM_PFX(LoadMicrocodeDefault)
460 SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).
461 ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.
462
463 ; Call Sec CAR Init
464 LOAD_RSP
465 CALL_YMM ASM_PFX(SecCarInit)
466 cmp rax, 0
467 jnz TempRamInitExit
468
469 LOAD_RSP
470 CALL_YMM ASM_PFX(EstablishStackFsp)
471 cmp rax, 0
472 jnz TempRamInitExit
473
474 LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).
475
476 TempRamInitExit:
477 mov bl, al ; save al data in bl
478 mov al, 07Fh ; API exit postcode 7f
479 out 080h, al
480 mov al, bl ; restore al data from bl
481
482 ;
483 ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6
484 ;
485 LOAD_REGS
486 LOAD_BFV rbp
487 ret
488
489 ;----------------------------------------------------------------------------
490 ; Module Entrypoint API
491 ;----------------------------------------------------------------------------
492 global ASM_PFX(_ModuleEntryPoint)
493 ASM_PFX(_ModuleEntryPoint):
494 jmp $
495