]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFsp2Pkg/FspSecCore/X64/FspApiEntryT.nasm
IntelFsp2Pkg: FSP_TEMP_RAM_INIT call must follow X64 Calling Convention
[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 ; rcx -> 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 cmp rcx, 0
134 jz ParamError
135 mov rsp, rcx
136
137 ; skip loading Microcode if the MicrocodeCodeSize is zero
138 ; and report error if size is less than 2k
139 ; first check UPD header revision
140 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
141 jb ParamError
142 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
143 jne ParamError
144
145 ; UPD structure is compliant with FSP spec 2.4
146 mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
147 cmp rax, 0
148 jz Exit2
149 cmp rax, 0800h
150 jl ParamError
151
152 mov rsi, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr]
153 cmp rsi, 0
154 jnz CheckMainHeader
155
156 ParamError:
157 mov rax, 08000000000000002h
158 jmp Exit2
159
160 CheckMainHeader:
161 ; Get processor signature and platform ID from the installed processor
162 ; and save into registers for later use
163 ; ebx = processor signature
164 ; edx = platform ID
165 mov eax, 1
166 cpuid
167 mov ebx, eax
168 mov ecx, MSR_IA32_PLATFORM_ID
169 rdmsr
170 mov ecx, edx
171 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits
172 and ecx, 7h ; platform id at bit[52..50]
173 mov edx, 1
174 shl edx, cl
175
176 ; Current register usage
177 ; esp -> stack with parameters
178 ; esi -> microcode update to check
179 ; ebx = processor signature
180 ; edx = platform ID
181
182 ; Check for valid microcode header
183 ; Minimal test checking for header version and loader version as 1
184 mov eax, dword 1
185 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax
186 jne AdvanceFixedSize
187 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax
188 jne AdvanceFixedSize
189
190 ; Check if signature and plaform ID match
191 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]
192 jne LoadMicrocodeDefault1
193 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]
194 jnz LoadCheck ; Jif signature and platform ID match
195
196 LoadMicrocodeDefault1:
197 ; Check if extended header exists
198 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid
199 xor rax, rax
200 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
201 je NextMicrocode
202 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax
203 je NextMicrocode
204
205 ; Then verify total size - sizeof header > data size
206 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
207 sub ecx, MicrocodeHdr.size
208 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
209 jng NextMicrocode ; Jif extended header does not exist
210
211 ; Set edi -> extended header
212 mov edi, esi
213 add edi, MicrocodeHdr.size
214 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]
215
216 ; Get count of extended structures
217 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]
218
219 ; Move pointer to first signature structure
220 add edi, ExtSigHdr.size
221
222 CheckExtSig:
223 ; Check if extended signature and platform ID match
224 cmp dword [edi + ExtSig.ExtSigProcessor], ebx
225 jne LoadMicrocodeDefault2
226 test dword [edi + ExtSig.ExtSigFlags], edx
227 jnz LoadCheck ; Jif signature and platform ID match
228 LoadMicrocodeDefault2:
229 ; Check if any more extended signatures exist
230 add edi, ExtSig.size
231 loop CheckExtSig
232
233 NextMicrocode:
234 ; Advance just after end of this microcode
235 xor rax, rax
236 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax
237 je LoadMicrocodeDefault3
238 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]
239 jmp CheckAddress
240 LoadMicrocodeDefault3:
241 add esi, dword 2048
242 jmp CheckAddress
243
244 AdvanceFixedSize:
245 ; Advance by 4X dwords
246 add esi, dword 1024
247
248 CheckAddress:
249 ; Check UPD header revision
250 cmp byte [rsp + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
251 jb ParamError
252 cmp byte [rsp + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
253 jne ParamError
254
255 ; UPD structure is compliant with FSP spec 2.4
256 ; Is automatic size detection ?
257 mov rax, qword [rsp + LoadMicrocodeParamsFsp24.MicrocodeCodeSize]
258 mov rcx, 0ffffffffffffffffh
259 cmp rax, rcx
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, rcx
325 ;
326 ; Enable FSP STACK
327 ;
328 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
329 mov esp, DWORD[rax]
330 mov rax, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
331 add esp, DWORD[rax]
332
333 sub esp, 4
334 mov dword[esp], DATA_LEN_OF_MCUD ; Size of the data region
335 sub esp, 4
336 mov dword[esp], 4455434Dh ; Signature of the data region 'MCUD'
337
338 ; check UPD structure revision (rdx + 8)
339 cmp byte [rdx + LoadMicrocodeParamsFsp24.FspUpdHeaderRevision], 2
340 jb ParamError1
341 cmp byte [rdx + LoadMicrocodeParamsFsp24.FsptArchRevision], 2
342 je Fsp24UpdHeader
343
344 ParamError1:
345 mov rax, 08000000000000002h
346 jmp EstablishStackFspExit
347
348 Fsp24UpdHeader:
349 ; UPD structure is compliant with FSP spec 2.4
350 xor rax, rax
351 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 18h
352 sub rsp, 8
353 mov qword[rsp], rax
354 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 10h
355 sub rsp, 8
356 mov qword[rsp], rax
357 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 8h
358 sub rsp, 8
359 mov qword[rsp], rax
360 mov rax, qword [rdx + LoadMicrocodeParamsFsp24.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0h
361 sub rsp, 8
362 mov qword[rsp], rax
363
364 ContinueAfterUpdPush:
365 ;
366 ; Save API entry/exit timestamp into stack
367 ;
368 sub esp, 4
369 mov dword[esp], DATA_LEN_OF_PER0 ; Size of the data region
370 sub esp, 4
371 mov dword[esp], 30524550h ; Signature of the data region 'PER0'
372 rdtsc
373 sub esp, 4
374 mov dword[esp], edx
375 sub esp, 4
376 mov dword[esp], eax
377 LOAD_TS rax
378 push rax
379
380 ;
381 ; Terminator for the data on stack
382 ;
383 push 0
384
385 ;
386 ; Set ECX/EDX to the BootLoader temporary memory range
387 ;
388 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
389 mov edx, [ecx]
390 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamSize))
391 add edx, [ecx]
392 mov rcx, ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))
393 sub edx, [ecx]
394 mov rcx, ASM_PFX(PcdGet32 (PcdTemporaryRamBase))
395 mov ecx, [ecx]
396
397 cmp ecx, edx ; If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.
398 jb EstablishStackFspSuccess
399 mov rax, 08000000000000003h ; EFI_UNSUPPORTED
400 jmp EstablishStackFspExit
401 EstablishStackFspSuccess:
402 xor rax, rax
403
404 EstablishStackFspExit:
405 RET_YMM
406
407 ;----------------------------------------------------------------------------
408 ; TempRamInit API
409 ;
410 ; This FSP API will load the microcode update, enable code caching for the
411 ; region specified by the boot loader and also setup a temporary stack to be
412 ; used till main memory is initialized.
413 ;
414 ;----------------------------------------------------------------------------
415 global ASM_PFX(TempRamInitApi)
416 ASM_PFX(TempRamInitApi):
417 ;
418 ; Ensure both SSE and AVX are enabled
419 ;
420 ENABLE_SSE
421 ENABLE_AVX
422 ;
423 ; Save Input Parameter in YMM10
424 ;
425 SAVE_RCX
426 ;
427 ; Save RBP, RBX, RSI, RDI and RSP in YMM7, YMM8 and YMM6
428 ;
429 SAVE_REGS
430
431 ;
432 ; Save BFV address in YMM9
433 ;
434 SAVE_BFV rbp
435
436 ;
437 ; Save timestamp into YMM6
438 ;
439 rdtsc
440 shl rdx, 32
441 or rax, rdx
442 SAVE_TS rax
443
444 ;
445 ; Check Parameter
446 ;
447 cmp rcx, 0
448 mov rcx, 08000000000000002h
449 jz TempRamInitExit
450
451 ;
452 ; Sec Platform Init
453 ;
454 CALL_YMM ASM_PFX(SecPlatformInit)
455 cmp eax, 0
456 jnz TempRamInitExit
457
458 ; Load microcode
459 LOAD_RCX
460 CALL_YMM ASM_PFX(LoadMicrocodeDefault)
461 SAVE_UCODE_STATUS rax ; Save microcode return status in SLOT 0 in YMM9 (upper 128bits).
462 ; @note If return value rax is not 0, microcode did not load, but continue and attempt to boot.
463
464 ; Call Sec CAR Init
465 LOAD_RCX
466 CALL_YMM ASM_PFX(SecCarInit)
467 cmp rax, 0
468 jnz TempRamInitExit
469
470 LOAD_RCX
471 CALL_YMM ASM_PFX(EstablishStackFsp)
472 cmp rax, 0
473 jnz TempRamInitExit
474
475 LOAD_UCODE_STATUS rax ; Restore microcode status if no CAR init error from SLOT 0 in YMM9 (upper 128bits).
476
477 TempRamInitExit:
478 mov bl, al ; save al data in bl
479 mov al, 07Fh ; API exit postcode 7f
480 out 080h, al
481 mov al, bl ; restore al data from bl
482
483 ;
484 ; Load RBP, RBX, RSI, RDI and RSP from YMM7, YMM8 and YMM6
485 ;
486 LOAD_REGS
487 LOAD_BFV rbp
488 ret
489
490 ;----------------------------------------------------------------------------
491 ; Module Entrypoint API
492 ;----------------------------------------------------------------------------
493 global ASM_PFX(_ModuleEntryPoint)
494 ASM_PFX(_ModuleEntryPoint):
495 jmp $
496