]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
MdePkg/BaseLib: Preserve EBX register and fix stack offset to LinearAddress in AsmFlu...
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.asm
... / ...
CommitLineData
1;; @file\r
2; Provide FSP API entry points.\r
3;\r
4; Copyright (c) 2014 - 2015, 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 .586p\r
15 .model flat,C\r
16 .code\r
17 .xmm\r
18\r
19INCLUDE SaveRestoreSse.inc\r
20INCLUDE MicrocodeLoad.inc\r
21\r
22;\r
23; Following are fixed PCDs\r
24;\r
25EXTERN PcdGet32(PcdTemporaryRamBase):DWORD\r
26EXTERN PcdGet32(PcdTemporaryRamSize):DWORD\r
27EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD\r
28EXTERN PcdGet32(PcdFspAreaSize):DWORD\r
29\r
30;\r
31; Following functions will be provided in C\r
32;\r
33\r
34EXTERN SecStartup:PROC\r
35EXTERN FspApiCallingCheck:PROC\r
36\r
37;\r
38; Following functions will be provided in PlatformSecLib\r
39;\r
40EXTERN AsmGetFspBaseAddress:PROC\r
41EXTERN AsmGetFspInfoHeader:PROC\r
42EXTERN GetBootFirmwareVolumeOffset:PROC\r
43EXTERN Loader2PeiSwitchStack:PROC\r
44EXTERN LoadMicrocode(LoadMicrocodeDefault):PROC\r
45EXTERN SecPlatformInit(SecPlatformInitDefault):PROC\r
46EXTERN SecCarInit:PROC\r
47\r
48;\r
49; Define the data length that we saved on the stack top\r
50;\r
51DATA_LEN_OF_PER0 EQU 18h\r
52DATA_LEN_OF_MCUD EQU 18h\r
53DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)\r
54\r
55;\r
56; Define SSE macros\r
57;\r
58LOAD_MMX_EXT MACRO ReturnAddress, MmxRegister\r
59 mov esi, ReturnAddress\r
60 movd MmxRegister, esi ; save ReturnAddress into MMX\r
61ENDM\r
62\r
63CALL_MMX_EXT MACRO RoutineLabel, MmxRegister\r
64 local ReturnAddress\r
65 mov esi, offset ReturnAddress\r
66 movd MmxRegister, esi ; save ReturnAddress into MMX\r
67 jmp RoutineLabel\r
68ReturnAddress:\r
69ENDM\r
70\r
71RET_ESI_EXT MACRO MmxRegister\r
72 movd esi, MmxRegister ; move ReturnAddress from MMX to ESI\r
73 jmp esi\r
74ENDM\r
75\r
76CALL_MMX MACRO RoutineLabel\r
77 CALL_MMX_EXT RoutineLabel, mm7\r
78ENDM\r
79\r
80RET_ESI MACRO\r
81 RET_ESI_EXT mm7\r
82ENDM\r
83\r
84;------------------------------------------------------------------------------\r
85SecPlatformInitDefault PROC NEAR PUBLIC\r
86 ; Inputs:\r
87 ; mm7 -> Return address\r
88 ; Outputs:\r
89 ; eax -> 0 - Successful, Non-zero - Failed.\r
90 ; Register Usage:\r
91 ; eax is cleared and ebp is used for return address.\r
92 ; All others reserved.\r
93 \r
94 ; Save return address to EBP\r
95 movd ebp, mm7\r
96\r
97 xor eax, eax\r
98exit:\r
99 jmp ebp\r
100SecPlatformInitDefault ENDP\r
101\r
102;------------------------------------------------------------------------------\r
103LoadMicrocodeDefault PROC NEAR PUBLIC\r
104 ; Inputs:\r
105 ; esp -> LoadMicrocodeParams pointer\r
106 ; Register Usage:\r
107 ; esp Preserved\r
108 ; All others destroyed\r
109 ; Assumptions:\r
110 ; No memory available, stack is hard-coded and used for return address\r
111 ; Executed by SBSP and NBSP\r
112 ; Beginning of microcode update region starts on paragraph boundary\r
113\r
114 ;\r
115 ;\r
116 ; Save return address to EBP\r
117 movd ebp, mm7\r
118\r
119 cmp esp, 0\r
120 jz paramerror\r
121 mov eax, dword ptr [esp + 4] ; Parameter pointer\r
122 cmp eax, 0\r
123 jz paramerror\r
124 mov esp, eax\r
125 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr\r
126 cmp esi, 0\r
127 jnz check_main_header\r
128\r
129paramerror:\r
130 mov eax, 080000002h\r
131 jmp exit\r
132\r
133 mov esi, [esp].LoadMicrocodeParams.MicrocodeCodeAddr\r
134\r
135check_main_header:\r
136 ; Get processor signature and platform ID from the installed processor\r
137 ; and save into registers for later use\r
138 ; ebx = processor signature\r
139 ; edx = platform ID\r
140 mov eax, 1\r
141 cpuid\r
142 mov ebx, eax\r
143 mov ecx, MSR_IA32_PLATFORM_ID\r
144 rdmsr\r
145 mov ecx, edx\r
146 shr ecx, 50-32\r
147 and ecx, 7h\r
148 mov edx, 1\r
149 shl edx, cl\r
150\r
151 ; Current register usage\r
152 ; esp -> stack with paramters\r
153 ; esi -> microcode update to check\r
154 ; ebx = processor signature\r
155 ; edx = platform ID\r
156\r
157 ; Check for valid microcode header\r
158 ; Minimal test checking for header version and loader version as 1\r
159 mov eax, dword ptr 1\r
160 cmp [esi].MicrocodeHdr.MicrocodeHdrVersion, eax\r
161 jne advance_fixed_size\r
162 cmp [esi].MicrocodeHdr.MicrocodeHdrLoader, eax\r
163 jne advance_fixed_size\r
164\r
165 ; Check if signature and plaform ID match\r
166 cmp ebx, [esi].MicrocodeHdr.MicrocodeHdrProcessor\r
167 jne @f\r
168 test edx, [esi].MicrocodeHdr.MicrocodeHdrFlags\r
169 jnz load_check ; Jif signature and platform ID match\r
170\r
171@@:\r
172 ; Check if extended header exists\r
173 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid\r
174 xor eax, eax\r
175 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax\r
176 je next_microcode\r
177 cmp [esi].MicrocodeHdr.MicrocodeHdrDataSize, eax\r
178 je next_microcode\r
179\r
180 ; Then verify total size - sizeof header > data size\r
181 mov ecx, [esi].MicrocodeHdr.MicrocodeHdrTotalSize\r
182 sub ecx, sizeof MicrocodeHdr\r
183 cmp ecx, [esi].MicrocodeHdr.MicrocodeHdrDataSize\r
184 jng next_microcode ; Jif extended header does not exist\r
185\r
186 ; Set edi -> extended header\r
187 mov edi, esi\r
188 add edi, sizeof MicrocodeHdr\r
189 add edi, [esi].MicrocodeHdr.MicrocodeHdrDataSize\r
190\r
191 ; Get count of extended structures\r
192 mov ecx, [edi].ExtSigHdr.ExtSigHdrCount\r
193\r
194 ; Move pointer to first signature structure\r
195 add edi, sizeof ExtSigHdr\r
196\r
197check_ext_sig:\r
198 ; Check if extended signature and platform ID match\r
199 cmp [edi].ExtSig.ExtSigProcessor, ebx\r
200 jne @f\r
201 test [edi].ExtSig.ExtSigFlags, edx\r
202 jnz load_check ; Jif signature and platform ID match\r
203@@:\r
204 ; Check if any more extended signatures exist\r
205 add edi, sizeof ExtSig\r
206 loop check_ext_sig\r
207\r
208next_microcode:\r
209 ; Advance just after end of this microcode\r
210 xor eax, eax\r
211 cmp [esi].MicrocodeHdr.MicrocodeHdrTotalSize, eax\r
212 je @f\r
213 add esi, [esi].MicrocodeHdr.MicrocodeHdrTotalSize\r
214 jmp check_address\r
215@@:\r
216 add esi, dword ptr 2048\r
217 jmp check_address\r
218\r
219advance_fixed_size:\r
220 ; Advance by 4X dwords\r
221 add esi, dword ptr 1024\r
222\r
223check_address:\r
224 ; Is valid Microcode start point ?\r
225 cmp dword ptr [esi].MicrocodeHdr.MicrocodeHdrVersion, 0ffffffffh\r
226 jz done\r
227\r
228 ; Is automatic size detection ?\r
229 mov eax, [esp].LoadMicrocodeParams.MicrocodeCodeSize\r
230 cmp eax, 0ffffffffh\r
231 jz @f\r
232\r
233 ; Address >= microcode region address + microcode region size?\r
234 add eax, [esp].LoadMicrocodeParams.MicrocodeCodeAddr\r
235 cmp esi, eax\r
236 jae done ;Jif address is outside of microcode region\r
237 jmp check_main_header\r
238\r
239@@:\r
240load_check:\r
241 ; Get the revision of the current microcode update loaded\r
242 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
243 xor eax, eax ; Clear EAX\r
244 xor edx, edx ; Clear EDX\r
245 wrmsr ; Load 0 to MSR at 8Bh\r
246\r
247 mov eax, 1\r
248 cpuid\r
249 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
250 rdmsr ; Get current microcode signature\r
251\r
252 ; Verify this microcode update is not already loaded\r
253 cmp [esi].MicrocodeHdr.MicrocodeHdrRevision, edx\r
254 je continue\r
255\r
256load_microcode:\r
257 ; EAX contains the linear address of the start of the Update Data\r
258 ; EDX contains zero\r
259 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)\r
260 ; Start microcode load with wrmsr\r
261 mov eax, esi\r
262 add eax, sizeof MicrocodeHdr\r
263 xor edx, edx\r
264 mov ecx, MSR_IA32_BIOS_UPDT_TRIG\r
265 wrmsr\r
266 mov eax, 1\r
267 cpuid\r
268\r
269continue:\r
270 jmp next_microcode\r
271\r
272done:\r
273 mov eax, 1\r
274 cpuid\r
275 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
276 rdmsr ; Get current microcode signature\r
277 xor eax, eax\r
278 cmp edx, 0\r
279 jnz exit\r
280 mov eax, 08000000Eh\r
281\r
282exit:\r
283 jmp ebp\r
284\r
285LoadMicrocodeDefault ENDP\r
286\r
287EstablishStackFsp PROC NEAR PRIVATE\r
288 ;\r
289 ; Save parameter pointer in edx\r
290 ;\r
291 mov edx, dword ptr [esp + 4]\r
292\r
293 ;\r
294 ; Enable FSP STACK\r
295 ;\r
296 mov esp, PcdGet32 (PcdTemporaryRamBase)\r
297 add esp, PcdGet32 (PcdTemporaryRamSize)\r
298\r
299 push DATA_LEN_OF_MCUD ; Size of the data region\r
300 push 4455434Dh ; Signature of the data region 'MCUD'\r
301 push dword ptr [edx + 12] ; Code size\r
302 push dword ptr [edx + 8] ; Code base\r
303 push dword ptr [edx + 4] ; Microcode size\r
304 push dword ptr [edx] ; Microcode base\r
305\r
306 ;\r
307 ; Save API entry/exit timestamp into stack\r
308 ;\r
309 push DATA_LEN_OF_PER0 ; Size of the data region \r
310 push 30524550h ; Signature of the data region 'PER0'\r
311 LOAD_EDX\r
312 push edx\r
313 LOAD_EAX\r
314 push eax\r
315 rdtsc\r
316 push edx\r
317 push eax\r
318\r
319 ;\r
320 ; Terminator for the data on stack\r
321 ; \r
322 push 0\r
323\r
324 ;\r
325 ; Set ECX/EDX to the BootLoader temporary memory range\r
326 ;\r
327 mov ecx, PcdGet32 (PcdTemporaryRamBase)\r
328 mov edx, ecx\r
329 add edx, PcdGet32 (PcdTemporaryRamSize)\r
330 sub edx, PcdGet32 (PcdFspTemporaryRamSize)\r
331\r
332 xor eax, eax\r
333\r
334 RET_ESI\r
335\r
336EstablishStackFsp ENDP\r
337\r
338\r
339;----------------------------------------------------------------------------\r
340; TempRamInit API\r
341;\r
342; This FSP API will load the microcode update, enable code caching for the\r
343; region specified by the boot loader and also setup a temporary stack to be\r
344; used till main memory is initialized.\r
345;\r
346;----------------------------------------------------------------------------\r
347TempRamInitApi PROC NEAR PUBLIC\r
348 ;\r
349 ; Ensure SSE is enabled\r
350 ;\r
351 ENABLE_SSE\r
352\r
353 ;\r
354 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6\r
355 ;\r
356 SAVE_REGS\r
357\r
358 ;\r
359 ; Save timestamp into XMM6\r
360 ;\r
361 rdtsc\r
362 SAVE_EAX\r
363 SAVE_EDX\r
364\r
365 ;\r
366 ; Check Parameter\r
367 ;\r
368 mov eax, dword ptr [esp + 4]\r
369 cmp eax, 0\r
370 mov eax, 80000002h\r
371 jz NemInitExit\r
372\r
373 ;\r
374 ; Sec Platform Init\r
375 ;\r
376 CALL_MMX SecPlatformInit\r
377 cmp eax, 0\r
378 jnz NemInitExit\r
379 \r
380 ; Load microcode\r
381 LOAD_ESP\r
382 CALL_MMX LoadMicrocode\r
383 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6.\r
384 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot.\r
385\r
386 ; Call Sec CAR Init\r
387 LOAD_ESP\r
388 CALL_MMX SecCarInit\r
389 cmp eax, 0\r
390 jnz NemInitExit\r
391\r
392 LOAD_ESP\r
393 CALL_MMX EstablishStackFsp\r
394\r
395 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6.\r
396\r
397NemInitExit:\r
398 ;\r
399 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6\r
400 ;\r
401 LOAD_REGS\r
402 ret\r
403TempRamInitApi ENDP\r
404\r
405;----------------------------------------------------------------------------\r
406; FspInit API\r
407;\r
408; This FSP API will perform the processor and chipset initialization.\r
409; This API will not return. Instead, it transfers the control to the\r
410; ContinuationFunc provided in the parameter.\r
411;\r
412;----------------------------------------------------------------------------\r
413FspInitApi PROC NEAR PUBLIC\r
414 mov eax, 1\r
415 jmp FspApiCommon\r
416 FspInitApi ENDP\r
417\r
418;----------------------------------------------------------------------------\r
419; NotifyPhase API\r
420;\r
421; This FSP API will notify the FSP about the different phases in the boot\r
422; process\r
423;\r
424;----------------------------------------------------------------------------\r
425NotifyPhaseApi PROC C PUBLIC\r
426 mov eax, 2\r
427 jmp FspApiCommon\r
428NotifyPhaseApi ENDP\r
429\r
430;----------------------------------------------------------------------------\r
431; FspMemoryInit API\r
432;\r
433; This FSP API is called after TempRamInit and initializes the memory.\r
434;\r
435;----------------------------------------------------------------------------\r
436FspMemoryInitApi PROC NEAR PUBLIC\r
437 mov eax, 3\r
438 jmp FspApiCommon\r
439FspMemoryInitApi ENDP\r
440\r
441\r
442;----------------------------------------------------------------------------\r
443; TempRamExitApi API\r
444;\r
445; This API tears down temporary RAM\r
446;\r
447;----------------------------------------------------------------------------\r
448TempRamExitApi PROC C PUBLIC\r
449 mov eax, 4\r
450 jmp FspApiCommon\r
451TempRamExitApi ENDP\r
452\r
453\r
454;----------------------------------------------------------------------------\r
455; FspSiliconInit API\r
456;\r
457; This FSP API initializes the CPU and the chipset including the IO\r
458; controllers in the chipset to enable normal operation of these devices.\r
459;\r
460;----------------------------------------------------------------------------\r
461FspSiliconInitApi PROC C PUBLIC\r
462 mov eax, 5\r
463 jmp FspApiCommon\r
464FspSiliconInitApi ENDP\r
465\r
466;----------------------------------------------------------------------------\r
467; FspApiCommon API\r
468;\r
469; This is the FSP API common entry point to resume the FSP execution\r
470;\r
471;----------------------------------------------------------------------------\r
472FspApiCommon PROC C PUBLIC\r
473 ;\r
474 ; EAX holds the API index\r
475 ;\r
476\r
477 ;\r
478 ; Stack must be ready\r
479 ; \r
480 push eax\r
481 add esp, 4\r
482 cmp eax, dword ptr [esp - 4]\r
483 jz @F\r
484 mov eax, 080000003h\r
485 jmp exit\r
486\r
487@@:\r
488 ;\r
489 ; Verify the calling condition\r
490 ;\r
491 pushad\r
492 push [esp + 4 * 8 + 4]\r
493 push eax\r
494 call FspApiCallingCheck\r
495 add esp, 8\r
496 cmp eax, 0\r
497 jz @F\r
498 mov dword ptr [esp + 4 * 7], eax\r
499 popad\r
500 ret\r
501\r
502@@:\r
503 popad\r
504 cmp eax, 1 ; FspInit API\r
505 jz @F\r
506 cmp eax, 3 ; FspMemoryInit API\r
507 jz @F\r
508\r
509 call AsmGetFspInfoHeader\r
510 jmp Loader2PeiSwitchStack\r
511\r
512@@:\r
513 ;\r
514 ; FspInit and FspMemoryInit APIs, setup the initial stack frame\r
515 ;\r
516 \r
517 ;\r
518 ; Place holder to store the FspInfoHeader pointer\r
519 ;\r
520 push eax\r
521\r
522 ;\r
523 ; Update the FspInfoHeader pointer\r
524 ;\r
525 push eax\r
526 call AsmGetFspInfoHeader\r
527 mov [esp + 4], eax\r
528 pop eax\r
529\r
530 ;\r
531 ; Create a Task Frame in the stack for the Boot Loader\r
532 ;\r
533 pushfd ; 2 pushf for 4 byte alignment\r
534 cli\r
535 pushad\r
536\r
537 ; Reserve 8 bytes for IDT save/restore\r
538 sub esp, 8\r
539 sidt fword ptr [esp]\r
540\r
541 ;\r
542 ; Setup new FSP stack\r
543 ;\r
544 mov edi, esp\r
545 mov esp, PcdGet32(PcdTemporaryRamBase)\r
546 add esp, PcdGet32(PcdTemporaryRamSize)\r
547 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)\r
548\r
549 ;\r
550 ; Pass the API Idx to SecStartup\r
551 ;\r
552 push eax\r
553 \r
554 ;\r
555 ; Pass the BootLoader stack to SecStartup\r
556 ;\r
557 push edi\r
558\r
559 ;\r
560 ; Pass entry point of the PEI core\r
561 ;\r
562 call AsmGetFspBaseAddress\r
563 mov edi, eax\r
564 add edi, PcdGet32 (PcdFspAreaSize) \r
565 sub edi, 20h\r
566 add eax, DWORD PTR ds:[edi]\r
567 push eax\r
568\r
569 ;\r
570 ; Pass BFV into the PEI Core\r
571 ; It uses relative address to calucate the actual boot FV base\r
572 ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and\r
573 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,\r
574 ; they are different. The code below can handle both cases.\r
575 ;\r
576 call AsmGetFspBaseAddress\r
577 mov edi, eax\r
578 call GetBootFirmwareVolumeOffset\r
579 add eax, edi\r
580 push eax\r
581\r
582 ;\r
583 ; Pass stack base and size into the PEI Core\r
584 ;\r
585 mov eax, PcdGet32(PcdTemporaryRamBase)\r
586 add eax, PcdGet32(PcdTemporaryRamSize)\r
587 sub eax, PcdGet32(PcdFspTemporaryRamSize)\r
588 push eax\r
589 push PcdGet32(PcdFspTemporaryRamSize)\r
590\r
591 ;\r
592 ; Pass Control into the PEI Core\r
593 ;\r
594 call SecStartup\r
595 add esp, 4\r
596exit:\r
597 ret\r
598\r
599FspApiCommon ENDP\r
600\r
601END\r