]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
IntelFrameworkPkg: 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
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
4c53eb72
YS
175\r
176 ; skip loading Microcode if the MicrocodeCodeSize is zero\r
177 ; and report error if size is less than 2k\r
178 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]\r
179 cmp eax, 0\r
180 jz Exit2\r
181 cmp eax, 0800h\r
182 jl ParamError\r
183\r
cf1d4549
JY
184 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]\r
185 cmp esi, 0\r
186 jnz CheckMainHeader\r
187\r
188ParamError:\r
189 mov eax, 080000002h\r
190 jmp Exit2\r
191\r
192CheckMainHeader:\r
193 ; Get processor signature and platform ID from the installed processor\r
194 ; and save into registers for later use\r
195 ; ebx = processor signature\r
196 ; edx = platform ID\r
197 mov eax, 1\r
198 cpuid\r
199 mov ebx, eax\r
200 mov ecx, MSR_IA32_PLATFORM_ID\r
201 rdmsr\r
202 mov ecx, edx\r
203 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits\r
204 and ecx, 7h ; platform id at bit[52..50]\r
205 mov edx, 1\r
206 shl edx, cl\r
207\r
208 ; Current register usage\r
209 ; esp -> stack with parameters\r
210 ; esi -> microcode update to check\r
211 ; ebx = processor signature\r
212 ; edx = platform ID\r
213\r
214 ; Check for valid microcode header\r
215 ; Minimal test checking for header version and loader version as 1\r
216 mov eax, dword 1\r
217 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax\r
218 jne AdvanceFixedSize\r
219 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax\r
220 jne AdvanceFixedSize\r
221\r
222 ; Check if signature and plaform ID match\r
223 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor]\r
224 jne LoadMicrocodeDefault1\r
225 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ]\r
226 jnz LoadCheck ; Jif signature and platform ID match\r
227\r
228LoadMicrocodeDefault1:\r
229 ; Check if extended header exists\r
230 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid\r
231 xor eax, eax\r
232 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax\r
233 je NextMicrocode\r
234 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax\r
235 je NextMicrocode\r
236\r
237 ; Then verify total size - sizeof header > data size\r
238 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]\r
239 sub ecx, MicrocodeHdr.size\r
240 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]\r
241 jng NextMicrocode ; Jif extended header does not exist\r
242\r
243 ; Set edi -> extended header\r
244 mov edi, esi\r
245 add edi, MicrocodeHdr.size\r
246 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize]\r
247\r
248 ; Get count of extended structures\r
249 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount]\r
250\r
251 ; Move pointer to first signature structure\r
252 add edi, ExtSigHdr.size\r
253\r
254CheckExtSig:\r
255 ; Check if extended signature and platform ID match\r
256 cmp dword [edi + ExtSig.ExtSigProcessor], ebx\r
257 jne LoadMicrocodeDefault2\r
258 test dword [edi + ExtSig.ExtSigFlags], edx\r
259 jnz LoadCheck ; Jif signature and platform ID match\r
260LoadMicrocodeDefault2:\r
261 ; Check if any more extended signatures exist\r
262 add edi, ExtSig.size\r
263 loop CheckExtSig\r
264\r
265NextMicrocode:\r
266 ; Advance just after end of this microcode\r
267 xor eax, eax\r
268 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax\r
269 je LoadMicrocodeDefault3\r
270 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize]\r
271 jmp CheckAddress\r
272LoadMicrocodeDefault3:\r
273 add esi, dword 2048\r
274 jmp CheckAddress\r
275\r
276AdvanceFixedSize:\r
277 ; Advance by 4X dwords\r
278 add esi, dword 1024\r
279\r
280CheckAddress:\r
281 ; Is valid Microcode start point ?\r
282 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh\r
283 jz Done\r
284\r
285 ; Is automatic size detection ?\r
286 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]\r
287 cmp eax, 0ffffffffh\r
288 jz LoadMicrocodeDefault4\r
289\r
290 ; Address >= microcode region address + microcode region size?\r
291 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]\r
292 cmp esi, eax\r
293 jae Done ;Jif address is outside of microcode region\r
294 jmp CheckMainHeader\r
295\r
296LoadMicrocodeDefault4:\r
297LoadCheck:\r
298 ; Get the revision of the current microcode update loaded\r
299 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
300 xor eax, eax ; Clear EAX\r
301 xor edx, edx ; Clear EDX\r
302 wrmsr ; Load 0 to MSR at 8Bh\r
303\r
304 mov eax, 1\r
305 cpuid\r
306 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
307 rdmsr ; Get current microcode signature\r
308\r
309 ; Verify this microcode update is not already loaded\r
310 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx\r
311 je Continue\r
312\r
313LoadMicrocode:\r
314 ; EAX contains the linear address of the start of the Update Data\r
315 ; EDX contains zero\r
316 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)\r
317 ; Start microcode load with wrmsr\r
318 mov eax, esi\r
319 add eax, MicrocodeHdr.size\r
320 xor edx, edx\r
321 mov ecx, MSR_IA32_BIOS_UPDT_TRIG\r
322 wrmsr\r
323 mov eax, 1\r
324 cpuid\r
325\r
326Continue:\r
327 jmp NextMicrocode\r
328\r
329Done:\r
330 mov eax, 1\r
331 cpuid\r
332 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
333 rdmsr ; Get current microcode signature\r
334 xor eax, eax\r
335 cmp edx, 0\r
336 jnz Exit2\r
337 mov eax, 08000000Eh\r
338\r
339Exit2:\r
340 jmp ebp\r
341\r
342\r
343global ASM_PFX(EstablishStackFsp)\r
344ASM_PFX(EstablishStackFsp):\r
345 ;\r
346 ; Save parameter pointer in edx\r
347 ;\r
348 mov edx, dword [esp + 4]\r
349\r
350 ;\r
351 ; Enable FSP STACK\r
352 ;\r
353 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]\r
354 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]\r
355\r
356 push DATA_LEN_OF_MCUD ; Size of the data region\r
357 push 4455434Dh ; Signature of the data region 'MCUD'\r
358 push dword [edx + 2Ch] ; Code size sizeof(FSPT_UPD_COMMON) + 12\r
359 push dword [edx + 28h] ; Code base sizeof(FSPT_UPD_COMMON) + 8\r
360 push dword [edx + 24h] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4\r
361 push dword [edx + 20h] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0\r
362\r
363 ;\r
364 ; Save API entry/exit timestamp into stack\r
365 ;\r
366 push DATA_LEN_OF_PER0 ; Size of the data region\r
367 push 30524550h ; Signature of the data region 'PER0'\r
368 rdtsc\r
369 push edx\r
370 push eax\r
371 LOAD_EDX\r
372 push edx\r
373 LOAD_EAX\r
374 push eax\r
375\r
376 ;\r
377 ; Terminator for the data on stack\r
378 ;\r
379 push 0\r
380\r
381 ;\r
382 ; Set ECX/EDX to the BootLoader temporary memory range\r
383 ;\r
384 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))]\r
385 mov edx, ecx\r
386 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))]\r
387 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))]\r
388\r
389 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error.\r
390 jb EstablishStackFspSuccess\r
391 mov eax, 80000003h ;EFI_UNSUPPORTED\r
392 jmp EstablishStackFspExit\r
393EstablishStackFspSuccess:\r
394 xor eax, eax\r
395\r
396EstablishStackFspExit:\r
397 RET_ESI\r
398\r
399;----------------------------------------------------------------------------\r
400; TempRamInit API\r
401;\r
402; This FSP API will load the microcode update, enable code caching for the\r
403; region specified by the boot loader and also setup a temporary stack to be\r
404; used till main memory is initialized.\r
405;\r
406;----------------------------------------------------------------------------\r
407global ASM_PFX(TempRamInitApi)\r
408ASM_PFX(TempRamInitApi):\r
409 ;\r
410 ; Ensure SSE is enabled\r
411 ;\r
412 ENABLE_SSE\r
413\r
414 ;\r
415 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6\r
416 ;\r
417 SAVE_REGS\r
418\r
419 ;\r
420 ; Save timestamp into XMM6\r
421 ;\r
422 rdtsc\r
423 SAVE_EAX\r
424 SAVE_EDX\r
425\r
426 ;\r
427 ; Check Parameter\r
428 ;\r
429 mov eax, dword [esp + 4]\r
430 cmp eax, 0\r
431 mov eax, 80000002h\r
432 jz TempRamInitExit\r
433\r
434 ;\r
435 ; Sec Platform Init\r
436 ;\r
437 CALL_MMX ASM_PFX(SecPlatformInit)\r
438 cmp eax, 0\r
439 jnz TempRamInitExit\r
440\r
441 ; Load microcode\r
442 LOAD_ESP\r
443 CALL_MMX ASM_PFX(LoadMicrocodeDefault)\r
444 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.\r
445 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.\r
446\r
447 ; Call Sec CAR Init\r
448 LOAD_ESP\r
449 CALL_MMX ASM_PFX(SecCarInit)\r
450 cmp eax, 0\r
451 jnz TempRamInitExit\r
452\r
453 LOAD_ESP\r
454 CALL_MMX ASM_PFX(EstablishStackFsp)\r
455 cmp eax, 0\r
456 jnz TempRamInitExit\r
457\r
458 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.\r
459\r
460TempRamInitExit:\r
461 mov bl, al ; save al data in bl\r
462 mov al, 07Fh ; API exit postcode 7f\r
463 out 080h, al\r
464 mov al, bl ; restore al data from bl\r
465\r
466 ;\r
467 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6\r
468 ;\r
469 LOAD_REGS\r
470 ret\r
471\r
472;----------------------------------------------------------------------------\r
473; Module Entrypoint API\r
474;----------------------------------------------------------------------------\r
475global ASM_PFX(_ModuleEntryPoint)\r
476ASM_PFX(_ModuleEntryPoint):\r
477 jmp $\r