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