]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
UefiCpuPkg: Remove FIT based microcode shadow logic from MpInitLib.
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / PeiMpLib.c
CommitLineData
3e8ad6bd
JF
1/** @file\r
2 MP initialize support functions for PEI phase.\r
3\r
348a34d9 4 Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>\r
0acd8697 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
3e8ad6bd
JF
6\r
7**/\r
8\r
9#include "MpLib.h"\r
58942277
ED
10#include <Library/PeiServicesLib.h>\r
11#include <Guid/S3SmmInitDone.h>\r
c788c2b1 12#include <Ppi/ShadowMicrocode.h>\r
58942277
ED
13\r
14/**\r
15 S3 SMM Init Done notification function.\r
16\r
17 @param PeiServices Indirect reference to the PEI Services Table.\r
18 @param NotifyDesc Address of the notification descriptor data structure.\r
19 @param InvokePpi Address of the PPI that was invoked.\r
20\r
21 @retval EFI_SUCCESS The function completes successfully.\r
22\r
23**/\r
24EFI_STATUS\r
25EFIAPI\r
26NotifyOnS3SmmInitDonePpi (\r
27 IN EFI_PEI_SERVICES **PeiServices,\r
28 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
29 IN VOID *InvokePpi\r
30 );\r
31\r
32\r
33//\r
34// Global function\r
35//\r
36EFI_PEI_NOTIFY_DESCRIPTOR mS3SmmInitDoneNotifyDesc = {\r
37 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
38 &gEdkiiS3SmmInitDoneGuid,\r
39 NotifyOnS3SmmInitDonePpi\r
40};\r
41\r
58942277
ED
42/**\r
43 S3 SMM Init Done notification function.\r
44\r
45 @param PeiServices Indirect reference to the PEI Services Table.\r
46 @param NotifyDesc Address of the notification descriptor data structure.\r
47 @param InvokePpi Address of the PPI that was invoked.\r
48\r
49 @retval EFI_SUCCESS The function completes successfully.\r
50\r
51**/\r
52EFI_STATUS\r
53EFIAPI\r
54NotifyOnS3SmmInitDonePpi (\r
55 IN EFI_PEI_SERVICES **PeiServices,\r
56 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
57 IN VOID *InvokePpi\r
58 )\r
59{\r
60 CPU_MP_DATA *CpuMpData;\r
61\r
62 CpuMpData = GetCpuMpData ();\r
63\r
64 //\r
65 // PiSmmCpuDxeSmm driver hardcode change the loop mode to HLT mode.\r
66 // So in this notify function, code need to check the current loop\r
67 // mode, if it is not HLT mode, code need to change loop mode back\r
68 // to the original mode.\r
69 //\r
70 if (CpuMpData->ApLoopMode != ApInHltLoop) {\r
71 CpuMpData->WakeUpByInitSipiSipi = TRUE;\r
72 }\r
73\r
74 return EFI_SUCCESS;\r
75}\r
76\r
43c9fdcc
JF
77\r
78/**\r
79 Enable Debug Agent to support source debugging on AP function.\r
80\r
81**/\r
82VOID\r
83EnableDebugAgent (\r
84 VOID\r
85 )\r
86{\r
87}\r
88\r
93ca4c0f
JF
89/**\r
90 Get pointer to CPU MP Data structure.\r
c563077a
RN
91 For BSP, the pointer is retrieved from HOB.\r
92 For AP, the structure is just after IDT.\r
93ca4c0f
JF
93\r
94 @return The pointer to CPU MP Data structure.\r
95**/\r
96CPU_MP_DATA *\r
97GetCpuMpData (\r
98 VOID\r
99 )\r
100{\r
c563077a
RN
101 CPU_MP_DATA *CpuMpData;\r
102 MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;\r
103 IA32_DESCRIPTOR Idtr;\r
93ca4c0f 104\r
c563077a
RN
105 ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);\r
106 if (ApicBaseMsr.Bits.BSP == 1) {\r
107 CpuMpData = GetCpuMpDataFromGuidedHob ();\r
108 ASSERT (CpuMpData != NULL);\r
109 } else {\r
110 AsmReadIdtr (&Idtr);\r
111 CpuMpData = (CPU_MP_DATA *) (Idtr.Base + Idtr.Limit + 1);\r
112 }\r
93ca4c0f
JF
113 return CpuMpData;\r
114}\r
115\r
116/**\r
117 Save the pointer to CPU MP Data structure.\r
118\r
119 @param[in] CpuMpData The pointer to CPU MP Data structure will be saved.\r
120**/\r
121VOID\r
122SaveCpuMpData (\r
123 IN CPU_MP_DATA *CpuMpData\r
124 )\r
125{\r
126 UINT64 Data64;\r
127 //\r
128 // Build location of CPU MP DATA buffer in HOB\r
129 //\r
130 Data64 = (UINT64) (UINTN) CpuMpData;\r
131 BuildGuidDataHob (\r
132 &mCpuInitMpLibHobGuid,\r
133 (VOID *) &Data64,\r
134 sizeof (UINT64)\r
135 );\r
136}\r
137\r
ed66e0e3
JF
138/**\r
139 Check if AP wakeup buffer is overlapped with existing allocated buffer.\r
140\r
141 @param[in] WakeupBufferStart AP wakeup buffer start address.\r
142 @param[in] WakeupBufferEnd AP wakeup buffer end address.\r
143\r
144 @retval TRUE There is overlap.\r
145 @retval FALSE There is no overlap.\r
146**/\r
147BOOLEAN\r
148CheckOverlapWithAllocatedBuffer (\r
5986cf38
RN
149 IN UINT64 WakeupBufferStart,\r
150 IN UINT64 WakeupBufferEnd\r
ed66e0e3
JF
151 )\r
152{\r
153 EFI_PEI_HOB_POINTERS Hob;\r
154 EFI_HOB_MEMORY_ALLOCATION *MemoryHob;\r
155 BOOLEAN Overlapped;\r
5986cf38
RN
156 UINT64 MemoryStart;\r
157 UINT64 MemoryEnd;\r
ed66e0e3
JF
158\r
159 Overlapped = FALSE;\r
160 //\r
161 // Get the HOB list for processing\r
162 //\r
163 Hob.Raw = GetHobList ();\r
164 //\r
165 // Collect memory ranges\r
166 //\r
167 while (!END_OF_HOB_LIST (Hob)) {\r
168 if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {\r
169 MemoryHob = Hob.MemoryAllocation;\r
5986cf38
RN
170 MemoryStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
171 MemoryEnd = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;\r
ed66e0e3
JF
172 if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {\r
173 Overlapped = TRUE;\r
174 break;\r
175 }\r
176 }\r
177 Hob.Raw = GET_NEXT_HOB (Hob);\r
178 }\r
179 return Overlapped;\r
180}\r
181\r
182/**\r
183 Get available system memory below 1MB by specified size.\r
184\r
185 @param[in] WakeupBufferSize Wakeup buffer size required\r
186\r
187 @retval other Return wakeup buffer address below 1MB.\r
188 @retval -1 Cannot find free memory below 1MB.\r
189**/\r
190UINTN\r
191GetWakeupBuffer (\r
192 IN UINTN WakeupBufferSize\r
193 )\r
194{\r
195 EFI_PEI_HOB_POINTERS Hob;\r
5986cf38
RN
196 UINT64 WakeupBufferStart;\r
197 UINT64 WakeupBufferEnd;\r
ed66e0e3
JF
198\r
199 WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);\r
200\r
201 //\r
202 // Get the HOB list for processing\r
203 //\r
204 Hob.Raw = GetHobList ();\r
205\r
206 //\r
207 // Collect memory ranges\r
208 //\r
209 while (!END_OF_HOB_LIST (Hob)) {\r
210 if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
211 if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&\r
212 (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&\r
213 ((Hob.ResourceDescriptor->ResourceAttribute &\r
214 (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |\r
215 EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |\r
216 EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED\r
217 )) == 0)\r
218 ) {\r
219 //\r
220 // Need memory under 1MB to be collected here\r
221 //\r
5986cf38 222 WakeupBufferEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength;\r
ed66e0e3
JF
223 if (WakeupBufferEnd > BASE_1MB) {\r
224 //\r
225 // Wakeup buffer should be under 1MB\r
226 //\r
227 WakeupBufferEnd = BASE_1MB;\r
228 }\r
229 while (WakeupBufferEnd > WakeupBufferSize) {\r
230 //\r
231 // Wakeup buffer should be aligned on 4KB\r
232 //\r
233 WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);\r
234 if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {\r
235 break;\r
236 }\r
237 if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {\r
238 //\r
239 // If this range is overlapped with existing allocated buffer, skip it\r
240 // and find the next range\r
241 //\r
242 WakeupBufferEnd -= WakeupBufferSize;\r
243 continue;\r
244 }\r
245 DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",\r
246 WakeupBufferStart, WakeupBufferSize));\r
5986cf38 247 return (UINTN)WakeupBufferStart;\r
ed66e0e3
JF
248 }\r
249 }\r
250 }\r
251 //\r
252 // Find the next HOB\r
253 //\r
254 Hob.Raw = GET_NEXT_HOB (Hob);\r
255 }\r
256\r
257 return (UINTN) -1;\r
258}\r
259\r
f32bfe6d
JW
260/**\r
261 Get available EfiBootServicesCode memory below 4GB by specified size.\r
262\r
263 This buffer is required to safely transfer AP from real address mode to\r
264 protected mode or long mode, due to the fact that the buffer returned by\r
265 GetWakeupBuffer() may be marked as non-executable.\r
266\r
267 @param[in] BufferSize Wakeup transition buffer size.\r
268\r
269 @retval other Return wakeup transition buffer address below 4GB.\r
270 @retval 0 Cannot find free memory below 4GB.\r
271**/\r
272UINTN\r
273GetModeTransitionBuffer (\r
274 IN UINTN BufferSize\r
275 )\r
276{\r
277 //\r
278 // PEI phase doesn't need to do such transition. So simply return 0.\r
279 //\r
280 return 0;\r
281}\r
282\r
08085f08
JF
283/**\r
284 Checks APs status and updates APs status if needed.\r
285\r
286**/\r
287VOID\r
288CheckAndUpdateApsStatus (\r
289 VOID\r
290 )\r
291{\r
292}\r
293\r
e1ed5573
HW
294/**\r
295 Build the microcode patch HOB that contains the base address and size of the\r
296 microcode patch stored in the memory.\r
297\r
298 @param[in] CpuMpData Pointer to the CPU_MP_DATA structure.\r
299\r
300**/\r
301VOID\r
302BuildMicrocodeCacheHob (\r
303 IN CPU_MP_DATA *CpuMpData\r
304 )\r
305{\r
306 EDKII_MICROCODE_PATCH_HOB *MicrocodeHob;\r
307 UINTN HobDataLength;\r
308 UINT32 Index;\r
309\r
310 HobDataLength = sizeof (EDKII_MICROCODE_PATCH_HOB) +\r
311 sizeof (UINT64) * CpuMpData->CpuCount;\r
312\r
313 MicrocodeHob = AllocatePool (HobDataLength);\r
314 if (MicrocodeHob == NULL) {\r
315 ASSERT (FALSE);\r
316 return;\r
317 }\r
318\r
319 //\r
320 // Store the information of the memory region that holds the microcode patches.\r
321 //\r
322 MicrocodeHob->MicrocodePatchAddress = CpuMpData->MicrocodePatchAddress;\r
323 MicrocodeHob->MicrocodePatchRegionSize = CpuMpData->MicrocodePatchRegionSize;\r
324\r
325 //\r
326 // Store the detected microcode patch for each processor as well.\r
327 //\r
328 MicrocodeHob->ProcessorCount = CpuMpData->CpuCount;\r
329 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
330 if (CpuMpData->CpuData[Index].MicrocodeEntryAddr != 0) {\r
331 MicrocodeHob->ProcessorSpecificPatchOffset[Index] =\r
332 CpuMpData->CpuData[Index].MicrocodeEntryAddr - CpuMpData->MicrocodePatchAddress;\r
333 } else {\r
334 MicrocodeHob->ProcessorSpecificPatchOffset[Index] = MAX_UINT64;\r
335 }\r
336 }\r
337\r
338 BuildGuidDataHob (\r
339 &gEdkiiMicrocodePatchHobGuid,\r
340 MicrocodeHob,\r
341 HobDataLength\r
342 );\r
343\r
344 return;\r
345}\r
346\r
93ca4c0f
JF
347/**\r
348 Initialize global data for MP support.\r
349\r
350 @param[in] CpuMpData The pointer to CPU MP Data structure.\r
351**/\r
352VOID\r
353InitMpGlobalData (\r
354 IN CPU_MP_DATA *CpuMpData\r
355 )\r
356{\r
58942277
ED
357 EFI_STATUS Status;\r
358\r
e1ed5573 359 BuildMicrocodeCacheHob (CpuMpData);\r
93ca4c0f 360 SaveCpuMpData (CpuMpData);\r
58942277
ED
361\r
362 ///\r
363 /// Install Notify\r
364 ///\r
365 Status = PeiServicesNotifyPpi (&mS3SmmInitDoneNotifyDesc);\r
366 ASSERT_EFI_ERROR (Status);\r
93ca4c0f
JF
367}\r
368\r
3e8ad6bd
JF
369/**\r
370 This service executes a caller provided function on all enabled APs.\r
371\r
372 @param[in] Procedure A pointer to the function to be run on\r
373 enabled APs of the system. See type\r
374 EFI_AP_PROCEDURE.\r
375 @param[in] SingleThread If TRUE, then all the enabled APs execute\r
376 the function specified by Procedure one by\r
377 one, in ascending order of processor handle\r
378 number. If FALSE, then all the enabled APs\r
379 execute the function specified by Procedure\r
380 simultaneously.\r
381 @param[in] WaitEvent The event created by the caller with CreateEvent()\r
382 service. If it is NULL, then execute in\r
383 blocking mode. BSP waits until all APs finish\r
384 or TimeoutInMicroSeconds expires. If it's\r
385 not NULL, then execute in non-blocking mode.\r
386 BSP requests the function specified by\r
387 Procedure to be started on all the enabled\r
388 APs, and go on executing immediately. If\r
389 all return from Procedure, or TimeoutInMicroSeconds\r
390 expires, this event is signaled. The BSP\r
391 can use the CheckEvent() or WaitForEvent()\r
392 services to check the state of event. Type\r
393 EFI_EVENT is defined in CreateEvent() in\r
394 the Unified Extensible Firmware Interface\r
395 Specification.\r
367284e7 396 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
3e8ad6bd
JF
397 APs to return from Procedure, either for\r
398 blocking or non-blocking mode. Zero means\r
399 infinity. If the timeout expires before\r
400 all APs return from Procedure, then Procedure\r
401 on the failed APs is terminated. All enabled\r
402 APs are available for next function assigned\r
403 by MpInitLibStartupAllAPs() or\r
404 MPInitLibStartupThisAP().\r
405 If the timeout expires in blocking mode,\r
406 BSP returns EFI_TIMEOUT. If the timeout\r
407 expires in non-blocking mode, WaitEvent\r
408 is signaled with SignalEvent().\r
409 @param[in] ProcedureArgument The parameter passed into Procedure for\r
410 all APs.\r
411 @param[out] FailedCpuList If NULL, this parameter is ignored. Otherwise,\r
412 if all APs finish successfully, then its\r
413 content is set to NULL. If not all APs\r
414 finish before timeout expires, then its\r
415 content is set to address of the buffer\r
416 holding handle numbers of the failed APs.\r
417 The buffer is allocated by MP Initialization\r
418 library, and it's the caller's responsibility to\r
419 free the buffer with FreePool() service.\r
420 In blocking mode, it is ready for consumption\r
421 when the call returns. In non-blocking mode,\r
422 it is ready when WaitEvent is signaled. The\r
423 list of failed CPU is terminated by\r
424 END_OF_CPU_LIST.\r
425\r
426 @retval EFI_SUCCESS In blocking mode, all APs have finished before\r
427 the timeout expired.\r
428 @retval EFI_SUCCESS In non-blocking mode, function has been dispatched\r
429 to all enabled APs.\r
430 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the\r
431 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was\r
432 signaled.\r
433 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not\r
434 supported.\r
435 @retval EFI_DEVICE_ERROR Caller processor is AP.\r
436 @retval EFI_NOT_STARTED No enabled APs exist in the system.\r
437 @retval EFI_NOT_READY Any enabled APs are busy.\r
438 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
439 @retval EFI_TIMEOUT In blocking mode, the timeout expired before\r
440 all enabled APs have finished.\r
441 @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
442\r
443**/\r
444EFI_STATUS\r
445EFIAPI\r
446MpInitLibStartupAllAPs (\r
447 IN EFI_AP_PROCEDURE Procedure,\r
448 IN BOOLEAN SingleThread,\r
449 IN EFI_EVENT WaitEvent OPTIONAL,\r
450 IN UINTN TimeoutInMicroseconds,\r
451 IN VOID *ProcedureArgument OPTIONAL,\r
452 OUT UINTN **FailedCpuList OPTIONAL\r
453 )\r
454{\r
86efe976
JF
455 if (WaitEvent != NULL) {\r
456 return EFI_UNSUPPORTED;\r
457 }\r
458\r
ee0c39fa 459 return StartupAllCPUsWorker (\r
86efe976
JF
460 Procedure,\r
461 SingleThread,\r
ee0c39fa 462 TRUE,\r
86efe976
JF
463 NULL,\r
464 TimeoutInMicroseconds,\r
465 ProcedureArgument,\r
466 FailedCpuList\r
467 );\r
3e8ad6bd
JF
468}\r
469\r
470/**\r
471 This service lets the caller get one enabled AP to execute a caller-provided\r
472 function.\r
473\r
474 @param[in] Procedure A pointer to the function to be run on the\r
475 designated AP of the system. See type\r
476 EFI_AP_PROCEDURE.\r
477 @param[in] ProcessorNumber The handle number of the AP. The range is\r
478 from 0 to the total number of logical\r
479 processors minus 1. The total number of\r
480 logical processors can be retrieved by\r
481 MpInitLibGetNumberOfProcessors().\r
482 @param[in] WaitEvent The event created by the caller with CreateEvent()\r
483 service. If it is NULL, then execute in\r
484 blocking mode. BSP waits until this AP finish\r
485 or TimeoutInMicroSeconds expires. If it's\r
486 not NULL, then execute in non-blocking mode.\r
487 BSP requests the function specified by\r
488 Procedure to be started on this AP,\r
489 and go on executing immediately. If this AP\r
490 return from Procedure or TimeoutInMicroSeconds\r
491 expires, this event is signaled. The BSP\r
492 can use the CheckEvent() or WaitForEvent()\r
493 services to check the state of event. Type\r
494 EFI_EVENT is defined in CreateEvent() in\r
495 the Unified Extensible Firmware Interface\r
496 Specification.\r
367284e7 497 @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for\r
3e8ad6bd
JF
498 this AP to finish this Procedure, either for\r
499 blocking or non-blocking mode. Zero means\r
500 infinity. If the timeout expires before\r
501 this AP returns from Procedure, then Procedure\r
502 on the AP is terminated. The\r
503 AP is available for next function assigned\r
504 by MpInitLibStartupAllAPs() or\r
505 MpInitLibStartupThisAP().\r
506 If the timeout expires in blocking mode,\r
507 BSP returns EFI_TIMEOUT. If the timeout\r
508 expires in non-blocking mode, WaitEvent\r
509 is signaled with SignalEvent().\r
510 @param[in] ProcedureArgument The parameter passed into Procedure on the\r
511 specified AP.\r
512 @param[out] Finished If NULL, this parameter is ignored. In\r
513 blocking mode, this parameter is ignored.\r
514 In non-blocking mode, if AP returns from\r
515 Procedure before the timeout expires, its\r
516 content is set to TRUE. Otherwise, the\r
517 value is set to FALSE. The caller can\r
518 determine if the AP returned from Procedure\r
519 by evaluating this value.\r
520\r
521 @retval EFI_SUCCESS In blocking mode, specified AP finished before\r
522 the timeout expires.\r
523 @retval EFI_SUCCESS In non-blocking mode, the function has been\r
524 dispatched to specified AP.\r
525 @retval EFI_UNSUPPORTED A non-blocking mode request was made after the\r
526 UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was\r
527 signaled.\r
528 @retval EFI_UNSUPPORTED WaitEvent is not NULL if non-blocking mode is not\r
529 supported.\r
530 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
531 @retval EFI_TIMEOUT In blocking mode, the timeout expired before\r
532 the specified AP has finished.\r
533 @retval EFI_NOT_READY The specified AP is busy.\r
534 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
535 @retval EFI_NOT_FOUND The processor with the handle specified by\r
536 ProcessorNumber does not exist.\r
537 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.\r
538 @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
539\r
540**/\r
541EFI_STATUS\r
542EFIAPI\r
543MpInitLibStartupThisAP (\r
544 IN EFI_AP_PROCEDURE Procedure,\r
545 IN UINTN ProcessorNumber,\r
546 IN EFI_EVENT WaitEvent OPTIONAL,\r
547 IN UINTN TimeoutInMicroseconds,\r
548 IN VOID *ProcedureArgument OPTIONAL,\r
549 OUT BOOLEAN *Finished OPTIONAL\r
550 )\r
551{\r
20ae5774
JF
552 if (WaitEvent != NULL) {\r
553 return EFI_UNSUPPORTED;\r
554 }\r
555\r
556 return StartupThisAPWorker (\r
557 Procedure,\r
558 ProcessorNumber,\r
559 NULL,\r
560 TimeoutInMicroseconds,\r
561 ProcedureArgument,\r
562 Finished\r
563 );\r
3e8ad6bd
JF
564}\r
565\r
566/**\r
567 This service switches the requested AP to be the BSP from that point onward.\r
568 This service changes the BSP for all purposes. This call can only be performed\r
569 by the current BSP.\r
570\r
571 @param[in] ProcessorNumber The handle number of AP that is to become the new\r
572 BSP. The range is from 0 to the total number of\r
573 logical processors minus 1. The total number of\r
574 logical processors can be retrieved by\r
575 MpInitLibGetNumberOfProcessors().\r
576 @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an\r
577 enabled AP. Otherwise, it will be disabled.\r
578\r
579 @retval EFI_SUCCESS BSP successfully switched.\r
580 @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to\r
581 this service returning.\r
582 @retval EFI_UNSUPPORTED Switching the BSP is not supported.\r
583 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
584 @retval EFI_NOT_FOUND The processor with the handle specified by\r
585 ProcessorNumber does not exist.\r
586 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or\r
587 a disabled AP.\r
588 @retval EFI_NOT_READY The specified AP is busy.\r
589 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
590\r
591**/\r
592EFI_STATUS\r
593EFIAPI\r
594MpInitLibSwitchBSP (\r
595 IN UINTN ProcessorNumber,\r
596 IN BOOLEAN EnableOldBSP\r
597 )\r
598{\r
41be0da5 599 return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);\r
3e8ad6bd
JF
600}\r
601\r
602/**\r
603 This service lets the caller enable or disable an AP from this point onward.\r
604 This service may only be called from the BSP.\r
605\r
606 @param[in] ProcessorNumber The handle number of AP.\r
607 The range is from 0 to the total number of\r
608 logical processors minus 1. The total number of\r
609 logical processors can be retrieved by\r
610 MpInitLibGetNumberOfProcessors().\r
611 @param[in] EnableAP Specifies the new state for the processor for\r
612 enabled, FALSE for disabled.\r
613 @param[in] HealthFlag If not NULL, a pointer to a value that specifies\r
614 the new health status of the AP. This flag\r
615 corresponds to StatusFlag defined in\r
616 EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only\r
617 the PROCESSOR_HEALTH_STATUS_BIT is used. All other\r
618 bits are ignored. If it is NULL, this parameter\r
619 is ignored.\r
620\r
621 @retval EFI_SUCCESS The specified AP was enabled or disabled successfully.\r
622 @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed\r
623 prior to this service returning.\r
624 @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported.\r
625 @retval EFI_DEVICE_ERROR The calling processor is an AP.\r
626 @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber\r
627 does not exist.\r
628 @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP.\r
629 @retval EFI_NOT_READY MP Initialize Library is not initialized.\r
630\r
631**/\r
632EFI_STATUS\r
633EFIAPI\r
634MpInitLibEnableDisableAP (\r
635 IN UINTN ProcessorNumber,\r
636 IN BOOLEAN EnableAP,\r
637 IN UINT32 *HealthFlag OPTIONAL\r
638 )\r
639{\r
e37109bc 640 return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);\r
3e8ad6bd
JF
641}\r
642\r
c788c2b1
SF
643/**\r
644 This funtion will try to invoke platform specific microcode shadow logic to\r
645 relocate microcode update patches into memory.\r
646\r
647 @param[in] CpuMpData The pointer to CPU MP Data structure.\r
3e8ad6bd 648\r
c788c2b1
SF
649 @retval EFI_SUCCESS Shadow microcode success.\r
650 @retval EFI_OUT_OF_RESOURCES No enough resource to complete the operation.\r
651 @retval EFI_UNSUPPORTED Can't find platform specific microcode shadow\r
652 PPI/Protocol.\r
653**/\r
654EFI_STATUS\r
655PlatformShadowMicrocode (\r
656 IN OUT CPU_MP_DATA *CpuMpData\r
657 )\r
658{\r
659 EFI_STATUS Status;\r
660 EDKII_PEI_SHADOW_MICROCODE_PPI *ShadowMicrocodePpi;\r
661 UINTN CpuCount;\r
662 EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId;\r
663 UINTN Index;\r
664 UINTN BufferSize;\r
665 VOID *Buffer;\r
666\r
667 Status = PeiServicesLocatePpi (\r
668 &gEdkiiPeiShadowMicrocodePpiGuid,\r
669 0,\r
670 NULL,\r
671 (VOID **) &ShadowMicrocodePpi\r
672 );\r
673 if (EFI_ERROR (Status)) {\r
674 return EFI_UNSUPPORTED;\r
675 }\r
676\r
677 CpuCount = CpuMpData->CpuCount;\r
678 MicrocodeCpuId = (EDKII_PEI_MICROCODE_CPU_ID *) AllocateZeroPool (sizeof (EDKII_PEI_MICROCODE_CPU_ID) * CpuCount);\r
679 if (MicrocodeCpuId == NULL) {\r
680 return EFI_OUT_OF_RESOURCES;\r
681 }\r
682\r
683 for (Index = 0; Index < CpuMpData->CpuCount; Index++) {\r
684 MicrocodeCpuId[Index].ProcessorSignature = CpuMpData->CpuData[Index].ProcessorSignature;\r
685 MicrocodeCpuId[Index].PlatformId = CpuMpData->CpuData[Index].PlatformId;\r
686 }\r
687\r
688 Status = ShadowMicrocodePpi->ShadowMicrocode (\r
689 ShadowMicrocodePpi,\r
690 CpuCount,\r
691 MicrocodeCpuId,\r
692 &BufferSize,\r
693 &Buffer\r
694 );\r
695 FreePool (MicrocodeCpuId);\r
696 if (EFI_ERROR (Status)) {\r
697 return EFI_NOT_FOUND;\r
698 }\r
699\r
700 CpuMpData->MicrocodePatchAddress = (UINTN) Buffer;\r
701 CpuMpData->MicrocodePatchRegionSize = BufferSize;\r
702\r
703 DEBUG ((\r
704 DEBUG_INFO,\r
705 "%a: Required microcode patches have been loaded at 0x%lx, with size 0x%lx.\n",\r
706 __FUNCTION__, CpuMpData->MicrocodePatchAddress, CpuMpData->MicrocodePatchRegionSize\r
707 ));\r
708\r
709 return EFI_SUCCESS;\r
710}\r