]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFspPkg/FspSecCore/Ia32/FspApiEntry.asm
Updated FspApiEntry.asm/.s to auto detect the size of the MCU region.
[mirror_edk2.git] / IntelFspPkg / FspSecCore / Ia32 / FspApiEntry.asm
CommitLineData
c8ec22a2
JY
1;------------------------------------------------------------------------------\r
2;\r
3; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
4; This program and the accompanying materials\r
5; are licensed and made available under the terms and conditions of the BSD License\r
6; which accompanies this distribution. The full text of the license may be found at\r
7; http://opensource.org/licenses/bsd-license.php.\r
8;\r
9; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11;\r
12; Abstract:\r
13;\r
14; Provide FSP API entry points.\r
15;\r
16;------------------------------------------------------------------------------\r
17\r
18 .586p\r
19 .model flat,C\r
20 .code\r
21 .xmm\r
22\r
23INCLUDE SaveRestoreSse.inc\r
24INCLUDE UcodeLoad.inc\r
25\r
26;\r
27; Following are fixed PCDs\r
28;\r
29EXTERN PcdGet32(PcdTemporaryRamBase):DWORD\r
30EXTERN PcdGet32(PcdTemporaryRamSize):DWORD\r
31EXTERN PcdGet32(PcdFspTemporaryRamSize):DWORD\r
32\r
33;\r
34; Following functions will be provided in C\r
35;\r
36EXTERN FspImageSizeOffset:DWORD\r
37EXTERN SecStartup:PROC\r
38EXTERN FspApiCallingCheck:PROC\r
39\r
40;\r
41; Following functions will be provided in PlatformSecLib\r
42;\r
43EXTERN GetFspBaseAddress:PROC\r
44EXTERN GetBootFirmwareVolumeOffset:PROC\r
45EXTERN PlatformTempRamInit:PROC\r
46EXTERN Pei2LoaderSwitchStack:PROC\r
47EXTERN FspSelfCheck(FspSelfCheckDflt):PROC\r
48EXTERN PlatformBasicInit(PlatformBasicInitDflt):PROC\r
49EXTERN LoadUcode(LoadUcodeDflt):PROC\r
50\r
51;\r
52; Define the data length that we saved on the stack top\r
53;\r
54DATA_LEN_OF_PER0 EQU 18h\r
55DATA_LEN_OF_MCUD EQU 18h\r
56DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4)\r
57\r
58;------------------------------------------------------------------------------\r
59FspSelfCheckDflt PROC NEAR PUBLIC\r
60 ; Inputs:\r
61 ; eax -> Return address\r
62 ; Outputs:\r
63 ; eax -> 0 - Successful, Non-zero - Failed.\r
64 ; Register Usage:\r
65 ; eax is cleared and ebp is used for return address.\r
66 ; All others reserved.\r
67\r
68 ; Save return address to EBP\r
69 mov ebp, eax\r
70\r
71 xor eax, eax\r
72exit:\r
73 jmp ebp\r
74FspSelfCheckDflt ENDP\r
75\r
76;------------------------------------------------------------------------------\r
77PlatformBasicInitDflt PROC NEAR PUBLIC\r
78 ; Inputs:\r
79 ; eax -> Return address\r
80 ; Outputs:\r
81 ; eax -> 0 - Successful, Non-zero - Failed.\r
82 ; Register Usage:\r
83 ; eax is cleared and ebp is used for return address.\r
84 ; All others reserved.\r
85\r
86 ; Save return address to EBP\r
87 mov ebp, eax\r
88\r
89 xor eax, eax\r
90exit:\r
91 jmp ebp\r
92PlatformBasicInitDflt ENDP\r
93\r
94;------------------------------------------------------------------------------\r
95LoadUcodeDflt PROC NEAR PUBLIC\r
96 ; Inputs:\r
97 ; esp -> LOAD_UCODE_PARAMS pointer\r
98 ; Register Usage:\r
99 ; esp Preserved\r
100 ; All others destroyed\r
101 ; Assumptions:\r
102 ; No memory available, stack is hard-coded and used for return address\r
103 ; Executed by SBSP and NBSP\r
104 ; Beginning of microcode update region starts on paragraph boundary\r
105\r
106 ;\r
107 ;\r
108 ; Save return address to EBP\r
109 mov ebp, eax\r
110\r
111 cmp esp, 0\r
112 jz paramerror\r
113 mov eax, dword ptr [esp] ; Parameter pointer\r
114 cmp eax, 0\r
115 jz paramerror\r
116 mov esp, eax\r
117 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr\r
118 cmp esi, 0\r
119 jnz check_main_header\r
120\r
121paramerror:\r
122 mov eax, 080000002h\r
123 jmp exit\r
124\r
125 mov esi, [esp].LOAD_UCODE_PARAMS.ucode_code_addr\r
126\r
127check_main_header:\r
128 ; Get processor signature and platform ID from the installed processor\r
129 ; and save into registers for later use\r
130 ; ebx = processor signature\r
131 ; edx = platform ID\r
132 mov eax, 1\r
133 cpuid\r
134 mov ebx, eax\r
135 mov ecx, MSR_IA32_PLATFORM_ID\r
136 rdmsr\r
137 mov ecx, edx\r
138 shr ecx, 50-32\r
139 and ecx, 7h\r
140 mov edx, 1\r
141 shl edx, cl\r
142\r
143 ; Current register usage\r
144 ; esp -> stack with paramters\r
145 ; esi -> microcode update to check\r
146 ; ebx = processor signature\r
147 ; edx = platform ID\r
148\r
149 ; Check for valid microcode header\r
150 ; Minimal test checking for header version and loader version as 1\r
151 mov eax, dword ptr 1\r
152 cmp [esi].ucode_hdr.version, eax\r
153 jne advance_fixed_size\r
154 cmp [esi].ucode_hdr.loader, eax\r
155 jne advance_fixed_size\r
156\r
157 ; Check if signature and plaform ID match\r
158 cmp ebx, [esi].ucode_hdr.processor\r
159 jne @f\r
160 test edx, [esi].ucode_hdr.flags\r
161 jnz load_check ; Jif signature and platform ID match\r
162\r
163@@:\r
164 ; Check if extended header exists\r
165 ; First check if total_size and data_size are valid\r
166 xor eax, eax\r
167 cmp [esi].ucode_hdr.total_size, eax\r
168 je next_microcode\r
169 cmp [esi].ucode_hdr.data_size, eax\r
170 je next_microcode\r
171\r
172 ; Then verify total size - sizeof header > data size\r
173 mov ecx, [esi].ucode_hdr.total_size\r
174 sub ecx, sizeof ucode_hdr\r
175 cmp ecx, [esi].ucode_hdr.data_size\r
176 jng next_microcode ; Jif extended header does not exist\r
177\r
178 ; Set edi -> extended header\r
179 mov edi, esi\r
180 add edi, sizeof ucode_hdr\r
181 add edi, [esi].ucode_hdr.data_size\r
182\r
183 ; Get count of extended structures\r
184 mov ecx, [edi].ext_sig_hdr.count\r
185\r
186 ; Move pointer to first signature structure\r
187 add edi, sizeof ext_sig_hdr\r
188\r
189check_ext_sig:\r
190 ; Check if extended signature and platform ID match\r
191 cmp [edi].ext_sig.processor, ebx\r
192 jne @f\r
193 test [edi].ext_sig.flags, edx\r
194 jnz load_check ; Jif signature and platform ID match\r
195@@:\r
196 ; Check if any more extended signatures exist\r
197 add edi, sizeof ext_sig\r
198 loop check_ext_sig\r
199\r
200next_microcode:\r
201 ; Advance just after end of this microcode\r
202 xor eax, eax\r
203 cmp [esi].ucode_hdr.total_size, eax\r
204 je @f\r
205 add esi, [esi].ucode_hdr.total_size\r
206 jmp check_address\r
207@@:\r
208 add esi, dword ptr 2048\r
209 jmp check_address\r
210\r
211advance_fixed_size:\r
212 ; Advance by 4X dwords\r
213 add esi, dword ptr 1024\r
214\r
215check_address:\r
216 ; Is valid Microcode start point ?\r
975f1c64 217 cmp dword ptr [esi].ucode_hdr.version, 0ffffffffh\r
c8ec22a2
JY
218 jz done\r
219\r
975f1c64
JY
220 ; Is automatic size detection ?\r
221 mov eax, [esp].LOAD_UCODE_PARAMS.ucode_code_size\r
222 cmp eax, 0ffffffffh\r
223 jz @f\r
224\r
c8ec22a2 225 ; Address >= microcode region address + microcode region size?\r
975f1c64 226 add eax, [esp].LOAD_UCODE_PARAMS.ucode_code_addr\r
c8ec22a2
JY
227 cmp esi, eax\r
228 jae done ;Jif address is outside of ucode region\r
229 jmp check_main_header\r
230\r
975f1c64 231@@:\r
c8ec22a2
JY
232load_check:\r
233 ; Get the revision of the current microcode update loaded\r
234 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
235 xor eax, eax ; Clear EAX\r
236 xor edx, edx ; Clear EDX\r
237 wrmsr ; Load 0 to MSR at 8Bh\r
238\r
239 mov eax, 1\r
240 cpuid\r
241 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
242 rdmsr ; Get current microcode signature\r
243\r
244 ; Verify this microcode update is not already loaded\r
245 cmp [esi].ucode_hdr.revision, edx\r
246 je continue\r
247\r
248load_microcode:\r
249 ; EAX contains the linear address of the start of the Update Data\r
250 ; EDX contains zero\r
251 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG)\r
252 ; Start microcode load with wrmsr\r
253 mov eax, esi\r
254 add eax, sizeof ucode_hdr\r
255 xor edx, edx\r
256 mov ecx, MSR_IA32_BIOS_UPDT_TRIG\r
257 wrmsr\r
258 mov eax, 1\r
259 cpuid\r
260\r
261continue:\r
262 jmp next_microcode\r
263\r
264done:\r
265 mov eax, 1\r
266 cpuid\r
267 mov ecx, MSR_IA32_BIOS_SIGN_ID\r
268 rdmsr ; Get current microcode signature\r
269 xor eax, eax\r
270 cmp edx, 0\r
271 jnz exit\r
272 mov eax, 08000000Eh\r
273\r
274exit:\r
275 jmp ebp\r
276\r
277LoadUcodeDflt ENDP\r
278\r
279;----------------------------------------------------------------------------\r
280; TempRamInit API\r
281;\r
282; This FSP API will load the microcode update, enable code caching for the\r
283; region specified by the boot loader and also setup a temporary stack to be\r
284; used till main memory is initialized.\r
285;\r
286;----------------------------------------------------------------------------\r
287TempRamInitApi PROC NEAR PUBLIC\r
288 ;\r
289 ; Ensure SSE is enabled\r
290 ;\r
291 ENABLE_SSE\r
292\r
293 ;\r
294 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6\r
295 ;\r
296 SAVE_REGS\r
297\r
298 ;\r
299 ; Save timestamp into XMM4 & XMM5\r
300 ;\r
301 rdtsc\r
302 SAVE_EAX\r
303 SAVE_EDX\r
304\r
305 ;\r
306 ; Check Parameter\r
307 ;\r
308 mov eax, dword ptr [esp + 4]\r
309 cmp eax, 0\r
310 mov eax, 80000002h\r
311 jz NemInitExit\r
312\r
313 ;\r
314 ; CPUID/DeviceID check\r
315 ;\r
316 mov eax, @F\r
317 jmp FspSelfCheck ; Note: ESP can not be changed.\r
318@@:\r
319 cmp eax, 0\r
320 jnz NemInitExit\r
321\r
322 ;\r
323 ; Platform Basic Init.\r
324 ;\r
325 mov eax, @F\r
326 jmp PlatformBasicInit\r
327@@:\r
328 cmp eax, 0\r
329 jnz NemInitExit\r
330\r
331 ;\r
332 ; Load microcode\r
333 ;\r
334 mov eax, @F\r
335 add esp, 4\r
336 jmp LoadUcode\r
337@@:\r
338 LOAD_ESP\r
339 cmp eax, 0\r
340 jnz NemInitExit\r
341\r
342 ;\r
343 ; Call platform NEM init\r
344 ;\r
345 mov eax, @F\r
346 add esp, 4\r
347 jmp PlatformTempRamInit\r
348@@:\r
349 LOAD_ESP\r
350 cmp eax, 0\r
351 jnz NemInitExit\r
352\r
353 ;\r
354 ; Save parameter pointer in edx\r
355 ;\r
356 mov edx, dword ptr [esp + 4]\r
357\r
358 ;\r
359 ; Enable FSP STACK\r
360 ;\r
361 mov esp, PcdGet32(PcdTemporaryRamBase)\r
362 add esp, PcdGet32(PcdTemporaryRamSize)\r
363\r
364 push DATA_LEN_OF_MCUD ; Size of the data region\r
365 push 4455434Dh ; Signature of the data region 'MCUD'\r
366 push dword ptr [edx + 4] ; Microcode size\r
367 push dword ptr [edx + 0] ; Microcode base\r
368 push dword ptr [edx + 12] ; Code size\r
369 push dword ptr [edx + 8] ; Code base\r
370\r
371 ;\r
372 ; Save API entry/exit timestamp into stack\r
373 ;\r
374 push DATA_LEN_OF_PER0 ; Size of the data region\r
375 push 30524550h ; Signature of the data region 'PER0'\r
376 rdtsc\r
377 push edx\r
378 push eax\r
379 LOAD_EAX\r
380 LOAD_EDX\r
381 push edx\r
382 push eax\r
383\r
384 ;\r
385 ; Terminator for the data on stack\r
386 ;\r
387 push 0\r
388\r
389 ;\r
390 ; Set ECX/EDX to the bootloader temporary memory range\r
391 ;\r
392 mov ecx, PcdGet32(PcdTemporaryRamBase)\r
393 mov edx, ecx\r
394 add edx, PcdGet32(PcdTemporaryRamSize)\r
395 sub edx, PcdGet32(PcdFspTemporaryRamSize)\r
396\r
397 xor eax, eax\r
398\r
399NemInitExit:\r
400 ;\r
401 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6\r
402 ;\r
403 LOAD_REGS\r
404 ret\r
405TempRamInitApi ENDP\r
406\r
407;----------------------------------------------------------------------------\r
408; FspInit API\r
409;\r
410; This FSP API will perform the processor and chipset initialization.\r
411; This API will not return. Instead, it transfers the control to the\r
412; ContinuationFunc provided in the parameter.\r
413;\r
414;----------------------------------------------------------------------------\r
415FspInitApi PROC NEAR PUBLIC\r
416 ;\r
417 ; Stack must be ready\r
418 ;\r
419 push 087654321h\r
420 pop eax\r
421 cmp eax, 087654321h\r
422 jz @F\r
423 mov eax, 080000003h\r
424 jmp exit\r
425\r
426@@:\r
427 ;\r
428 ; Additional check\r
429 ;\r
430 pushad\r
431 push 1\r
432 call FspApiCallingCheck\r
433 add esp, 4\r
434 mov dword ptr [esp + 4 * 7], eax\r
435 popad\r
436 cmp eax, 0\r
437 jz @F\r
438 jmp exit\r
439\r
440@@:\r
441 ;\r
442 ; Store the address in FSP which will return control to the BL\r
443 ;\r
444 push offset exit\r
445\r
446 ;\r
447 ; Create a Task Frame in the stack for the Boot Loader\r
448 ;\r
449 pushfd ; 2 pushf for 4 byte alignment\r
450 cli\r
451 pushad\r
452\r
453 ; Reserve 8 bytes for IDT save/restore\r
454 sub esp, 8\r
455 sidt fword ptr [esp]\r
456\r
457 ;\r
458 ; Setup new FSP stack\r
459 ;\r
460 mov eax, esp\r
461 mov esp, PcdGet32(PcdTemporaryRamBase)\r
462 add esp, PcdGet32(PcdTemporaryRamSize)\r
463 sub esp, (DATA_LEN_AT_STACK_TOP + 40h)\r
464\r
465 ;\r
466 ; Save the bootloader's stack pointer\r
467 ;\r
468 push eax\r
469\r
470 ;\r
471 ; Pass entry point of the PEI core\r
472 ;\r
473 call GetFspBaseAddress\r
474 mov edi, FspImageSizeOffset\r
475 mov edi, DWORD PTR [eax + edi]\r
476 add edi, eax\r
477 sub edi, 20h\r
478 add eax, DWORD PTR [edi]\r
479 push eax\r
480\r
481 ;\r
482 ; Pass BFV into the PEI Core\r
483 ; It uses relative address to calucate the actual boot FV base\r
484 ; For FSP impleantion with single FV, PcdFlashFvRecoveryBase and\r
485 ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs,\r
486 ; they are different. The code below can handle both cases.\r
487 ;\r
488 call GetFspBaseAddress\r
489 mov edi, eax\r
490 call GetBootFirmwareVolumeOffset\r
491 add eax, edi\r
492 push eax\r
493\r
494 ;\r
495 ; Pass stack base and size into the PEI Core\r
496 ;\r
497 mov eax, PcdGet32(PcdTemporaryRamBase)\r
498 add eax, PcdGet32(PcdTemporaryRamSize)\r
499 sub eax, PcdGet32(PcdFspTemporaryRamSize)\r
500 push eax\r
501 push PcdGet32(PcdFspTemporaryRamSize)\r
502\r
503 ;\r
504 ; Pass Control into the PEI Core\r
505 ;\r
506 call SecStartup\r
507\r
508exit:\r
509 ret\r
510\r
511FspInitApi ENDP\r
512\r
513;----------------------------------------------------------------------------\r
514; NotifyPhase API\r
515;\r
516; This FSP API will notify the FSP about the different phases in the boot\r
517; process\r
518;\r
519;----------------------------------------------------------------------------\r
520NotifyPhaseApi PROC C PUBLIC\r
521 ;\r
522 ; Stack must be ready\r
523 ;\r
524 push 087654321h\r
525 pop eax\r
526 cmp eax, 087654321h\r
527 jz @F\r
528 mov eax, 080000003h\r
529 jmp err_exit\r
530\r
531@@:\r
532 ;\r
533 ; Verify the calling condition\r
534 ;\r
535 pushad\r
536 push 2\r
537 call FspApiCallingCheck\r
538 add esp, 4\r
539 mov dword ptr [esp + 4 * 7], eax\r
540 popad\r
541\r
542 cmp eax, 0\r
543 jz @F\r
544\r
545 ;\r
546 ; Error return\r
547 ;\r
548err_exit:\r
549 ret\r
550\r
551@@:\r
552 jmp Pei2LoaderSwitchStack\r
553\r
554NotifyPhaseApi ENDP\r
555\r
556\r
557END\r