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