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