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