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