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