• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   MP initialize support functions for PEI phase.
3 
4   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "MpLib.h"
16 #include <Ppi/EndOfPeiPhase.h>
17 #include <Library/PeiServicesLib.h>
18 
19 //
20 // Global PEI notify function descriptor on EndofPei event
21 //
22 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_NOTIFY_DESCRIPTOR mMpInitLibNotifyList = {
23   (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
24   &gEfiEndOfPeiSignalPpiGuid,
25   CpuMpEndOfPeiCallback
26 };
27 
28 
29 /**
30   Enable Debug Agent to support source debugging on AP function.
31 
32 **/
33 VOID
EnableDebugAgent(VOID)34 EnableDebugAgent (
35   VOID
36   )
37 {
38 }
39 
40 /**
41   Get pointer to CPU MP Data structure.
42 
43   @return  The pointer to CPU MP Data structure.
44 **/
45 CPU_MP_DATA *
GetCpuMpData(VOID)46 GetCpuMpData (
47   VOID
48   )
49 {
50   CPU_MP_DATA      *CpuMpData;
51 
52   CpuMpData = GetCpuMpDataFromGuidedHob ();
53   ASSERT (CpuMpData != NULL);
54   return CpuMpData;
55 }
56 
57 /**
58   Save the pointer to CPU MP Data structure.
59 
60   @param[in] CpuMpData  The pointer to CPU MP Data structure will be saved.
61 **/
62 VOID
SaveCpuMpData(IN CPU_MP_DATA * CpuMpData)63 SaveCpuMpData (
64   IN CPU_MP_DATA   *CpuMpData
65   )
66 {
67   UINT64           Data64;
68   //
69   // Build location of CPU MP DATA buffer in HOB
70   //
71   Data64 = (UINT64) (UINTN) CpuMpData;
72   BuildGuidDataHob (
73     &mCpuInitMpLibHobGuid,
74     (VOID *) &Data64,
75     sizeof (UINT64)
76     );
77 }
78 
79 /**
80   Notify function on End Of PEI PPI.
81 
82   On S3 boot, this function will restore wakeup buffer data.
83   On normal boot, this function will flag wakeup buffer to be un-used type.
84 
85   @param[in]  PeiServices        The pointer to the PEI Services Table.
86   @param[in]  NotifyDescriptor   Address of the notification descriptor data structure.
87   @param[in]  Ppi                Address of the PPI that was installed.
88 
89   @retval EFI_SUCCESS        When everything is OK.
90 **/
91 EFI_STATUS
92 EFIAPI
CpuMpEndOfPeiCallback(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_NOTIFY_DESCRIPTOR * NotifyDescriptor,IN VOID * Ppi)93 CpuMpEndOfPeiCallback (
94   IN EFI_PEI_SERVICES             **PeiServices,
95   IN EFI_PEI_NOTIFY_DESCRIPTOR    *NotifyDescriptor,
96   IN VOID                         *Ppi
97   )
98 {
99   EFI_STATUS                Status;
100   EFI_BOOT_MODE             BootMode;
101   CPU_MP_DATA               *CpuMpData;
102   EFI_PEI_HOB_POINTERS      Hob;
103   EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
104 
105   DEBUG ((DEBUG_INFO, "PeiMpInitLib: CpuMpEndOfPeiCallback () invoked\n"));
106 
107   Status = PeiServicesGetBootMode (&BootMode);
108   ASSERT_EFI_ERROR (Status);
109 
110   CpuMpData = GetCpuMpData ();
111   if (BootMode != BOOT_ON_S3_RESUME) {
112     //
113     // Get the HOB list for processing
114     //
115     Hob.Raw = GetHobList ();
116     //
117     // Collect memory ranges
118     //
119     while (!END_OF_HOB_LIST (Hob)) {
120       if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
121         MemoryHob = Hob.MemoryAllocation;
122         if (MemoryHob->AllocDescriptor.MemoryBaseAddress == CpuMpData->WakeupBuffer) {
123           //
124           // Flag this HOB type to un-used
125           //
126           GET_HOB_TYPE (Hob) = EFI_HOB_TYPE_UNUSED;
127           break;
128         }
129       }
130       Hob.Raw = GET_NEXT_HOB (Hob);
131     }
132   } else {
133     CpuMpData->SaveRestoreFlag = TRUE;
134     RestoreWakeupBuffer (CpuMpData);
135   }
136   return EFI_SUCCESS;
137 }
138 
139 /**
140   Check if AP wakeup buffer is overlapped with existing allocated buffer.
141 
142   @param[in]  WakeupBufferStart     AP wakeup buffer start address.
143   @param[in]  WakeupBufferEnd       AP wakeup buffer end address.
144 
145   @retval  TRUE       There is overlap.
146   @retval  FALSE      There is no overlap.
147 **/
148 BOOLEAN
CheckOverlapWithAllocatedBuffer(IN UINTN WakeupBufferStart,IN UINTN WakeupBufferEnd)149 CheckOverlapWithAllocatedBuffer (
150   IN UINTN                WakeupBufferStart,
151   IN UINTN                WakeupBufferEnd
152   )
153 {
154   EFI_PEI_HOB_POINTERS      Hob;
155   EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
156   BOOLEAN                   Overlapped;
157   UINTN                     MemoryStart;
158   UINTN                     MemoryEnd;
159 
160   Overlapped = FALSE;
161   //
162   // Get the HOB list for processing
163   //
164   Hob.Raw = GetHobList ();
165   //
166   // Collect memory ranges
167   //
168   while (!END_OF_HOB_LIST (Hob)) {
169     if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
170       MemoryHob   = Hob.MemoryAllocation;
171       MemoryStart = (UINTN) MemoryHob->AllocDescriptor.MemoryBaseAddress;
172       MemoryEnd   = (UINTN) (MemoryHob->AllocDescriptor.MemoryBaseAddress +
173                              MemoryHob->AllocDescriptor.MemoryLength);
174       if (!((WakeupBufferStart >= MemoryEnd) || (WakeupBufferEnd <= MemoryStart))) {
175         Overlapped = TRUE;
176         break;
177       }
178     }
179     Hob.Raw = GET_NEXT_HOB (Hob);
180   }
181   return Overlapped;
182 }
183 
184 /**
185   Get available system memory below 1MB by specified size.
186 
187   @param[in] WakeupBufferSize   Wakeup buffer size required
188 
189   @retval other   Return wakeup buffer address below 1MB.
190   @retval -1      Cannot find free memory below 1MB.
191 **/
192 UINTN
GetWakeupBuffer(IN UINTN WakeupBufferSize)193 GetWakeupBuffer (
194   IN UINTN                WakeupBufferSize
195   )
196 {
197   EFI_PEI_HOB_POINTERS    Hob;
198   UINTN                   WakeupBufferStart;
199   UINTN                   WakeupBufferEnd;
200 
201   WakeupBufferSize = (WakeupBufferSize + SIZE_4KB - 1) & ~(SIZE_4KB - 1);
202 
203   //
204   // Get the HOB list for processing
205   //
206   Hob.Raw = GetHobList ();
207 
208   //
209   // Collect memory ranges
210   //
211   while (!END_OF_HOB_LIST (Hob)) {
212     if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
213       if ((Hob.ResourceDescriptor->PhysicalStart < BASE_1MB) &&
214           (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
215           ((Hob.ResourceDescriptor->ResourceAttribute &
216             (EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |
217              EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |
218              EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED
219              )) == 0)
220            ) {
221         //
222         // Need memory under 1MB to be collected here
223         //
224         WakeupBufferEnd = (UINTN) (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength);
225         if (WakeupBufferEnd > BASE_1MB) {
226           //
227           // Wakeup buffer should be under 1MB
228           //
229           WakeupBufferEnd = BASE_1MB;
230         }
231         while (WakeupBufferEnd > WakeupBufferSize) {
232           //
233           // Wakeup buffer should be aligned on 4KB
234           //
235           WakeupBufferStart = (WakeupBufferEnd - WakeupBufferSize) & ~(SIZE_4KB - 1);
236           if (WakeupBufferStart < Hob.ResourceDescriptor->PhysicalStart) {
237             break;
238           }
239           if (CheckOverlapWithAllocatedBuffer (WakeupBufferStart, WakeupBufferEnd)) {
240             //
241             // If this range is overlapped with existing allocated buffer, skip it
242             // and find the next range
243             //
244             WakeupBufferEnd -= WakeupBufferSize;
245             continue;
246           }
247           DEBUG ((DEBUG_INFO, "WakeupBufferStart = %x, WakeupBufferSize = %x\n",
248                                WakeupBufferStart, WakeupBufferSize));
249           //
250           // Create a memory allocation HOB.
251           //
252           BuildMemoryAllocationHob (
253             WakeupBufferStart,
254             WakeupBufferSize,
255             EfiBootServicesData
256             );
257           return WakeupBufferStart;
258         }
259       }
260     }
261     //
262     // Find the next HOB
263     //
264     Hob.Raw = GET_NEXT_HOB (Hob);
265   }
266 
267   return (UINTN) -1;
268 }
269 
270 /**
271   Allocate reset vector buffer.
272 
273   @param[in, out]  CpuMpData  The pointer to CPU MP Data structure.
274 **/
275 VOID
AllocateResetVector(IN OUT CPU_MP_DATA * CpuMpData)276 AllocateResetVector (
277   IN OUT CPU_MP_DATA          *CpuMpData
278   )
279 {
280   UINTN           ApResetVectorSize;
281 
282   if (CpuMpData->WakeupBuffer == (UINTN) -1) {
283     ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +
284                           sizeof (MP_CPU_EXCHANGE_INFO);
285 
286     CpuMpData->WakeupBuffer      = GetWakeupBuffer (ApResetVectorSize);
287     CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)
288                     (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);
289     BackupAndPrepareWakeupBuffer (CpuMpData);
290   }
291 
292   if (CpuMpData->SaveRestoreFlag) {
293     BackupAndPrepareWakeupBuffer (CpuMpData);
294   }
295 }
296 
297 /**
298   Free AP reset vector buffer.
299 
300   @param[in]  CpuMpData  The pointer to CPU MP Data structure.
301 **/
302 VOID
FreeResetVector(IN CPU_MP_DATA * CpuMpData)303 FreeResetVector (
304   IN CPU_MP_DATA              *CpuMpData
305   )
306 {
307   if (CpuMpData->SaveRestoreFlag) {
308     RestoreWakeupBuffer (CpuMpData);
309   }
310 }
311 
312 /**
313   Checks APs status and updates APs status if needed.
314 
315 **/
316 VOID
CheckAndUpdateApsStatus(VOID)317 CheckAndUpdateApsStatus (
318   VOID
319   )
320 {
321 }
322 
323 /**
324   Initialize global data for MP support.
325 
326   @param[in] CpuMpData  The pointer to CPU MP Data structure.
327 **/
328 VOID
InitMpGlobalData(IN CPU_MP_DATA * CpuMpData)329 InitMpGlobalData (
330   IN CPU_MP_DATA               *CpuMpData
331   )
332 {
333   EFI_STATUS      Status;
334 
335   SaveCpuMpData (CpuMpData);
336 
337   if (CpuMpData->CpuCount == 1) {
338     //
339     // If only BSP exists, return
340     //
341     return;
342   }
343 
344   //
345   // Register an event for EndOfPei
346   //
347   Status  = PeiServicesNotifyPpi (&mMpInitLibNotifyList);
348   ASSERT_EFI_ERROR (Status);
349 }
350 
351 /**
352   This service executes a caller provided function on all enabled APs.
353 
354   @param[in]  Procedure               A pointer to the function to be run on
355                                       enabled APs of the system. See type
356                                       EFI_AP_PROCEDURE.
357   @param[in]  SingleThread            If TRUE, then all the enabled APs execute
358                                       the function specified by Procedure one by
359                                       one, in ascending order of processor handle
360                                       number.  If FALSE, then all the enabled APs
361                                       execute the function specified by Procedure
362                                       simultaneously.
363   @param[in]  WaitEvent               The event created by the caller with CreateEvent()
364                                       service.  If it is NULL, then execute in
365                                       blocking mode. BSP waits until all APs finish
366                                       or TimeoutInMicroSeconds expires.  If it's
367                                       not NULL, then execute in non-blocking mode.
368                                       BSP requests the function specified by
369                                       Procedure to be started on all the enabled
370                                       APs, and go on executing immediately. If
371                                       all return from Procedure, or TimeoutInMicroSeconds
372                                       expires, this event is signaled. The BSP
373                                       can use the CheckEvent() or WaitForEvent()
374                                       services to check the state of event.  Type
375                                       EFI_EVENT is defined in CreateEvent() in
376                                       the Unified Extensible Firmware Interface
377                                       Specification.
378   @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
379                                       APs to return from Procedure, either for
380                                       blocking or non-blocking mode. Zero means
381                                       infinity.  If the timeout expires before
382                                       all APs return from Procedure, then Procedure
383                                       on the failed APs is terminated. All enabled
384                                       APs are available for next function assigned
385                                       by MpInitLibStartupAllAPs() or
386                                       MPInitLibStartupThisAP().
387                                       If the timeout expires in blocking mode,
388                                       BSP returns EFI_TIMEOUT.  If the timeout
389                                       expires in non-blocking mode, WaitEvent
390                                       is signaled with SignalEvent().
391   @param[in]  ProcedureArgument       The parameter passed into Procedure for
392                                       all APs.
393   @param[out] FailedCpuList           If NULL, this parameter is ignored. Otherwise,
394                                       if all APs finish successfully, then its
395                                       content is set to NULL. If not all APs
396                                       finish before timeout expires, then its
397                                       content is set to address of the buffer
398                                       holding handle numbers of the failed APs.
399                                       The buffer is allocated by MP Initialization
400                                       library, and it's the caller's responsibility to
401                                       free the buffer with FreePool() service.
402                                       In blocking mode, it is ready for consumption
403                                       when the call returns. In non-blocking mode,
404                                       it is ready when WaitEvent is signaled.  The
405                                       list of failed CPU is terminated by
406                                       END_OF_CPU_LIST.
407 
408   @retval EFI_SUCCESS             In blocking mode, all APs have finished before
409                                   the timeout expired.
410   @retval EFI_SUCCESS             In non-blocking mode, function has been dispatched
411                                   to all enabled APs.
412   @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
413                                   UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
414                                   signaled.
415   @retval EFI_UNSUPPORTED         WaitEvent is not NULL if non-blocking mode is not
416                                   supported.
417   @retval EFI_DEVICE_ERROR        Caller processor is AP.
418   @retval EFI_NOT_STARTED         No enabled APs exist in the system.
419   @retval EFI_NOT_READY           Any enabled APs are busy.
420   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
421   @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
422                                   all enabled APs have finished.
423   @retval EFI_INVALID_PARAMETER   Procedure is NULL.
424 
425 **/
426 EFI_STATUS
427 EFIAPI
MpInitLibStartupAllAPs(IN EFI_AP_PROCEDURE Procedure,IN BOOLEAN SingleThread,IN EFI_EVENT WaitEvent OPTIONAL,IN UINTN TimeoutInMicroseconds,IN VOID * ProcedureArgument OPTIONAL,OUT UINTN ** FailedCpuList OPTIONAL)428 MpInitLibStartupAllAPs (
429   IN  EFI_AP_PROCEDURE          Procedure,
430   IN  BOOLEAN                   SingleThread,
431   IN  EFI_EVENT                 WaitEvent               OPTIONAL,
432   IN  UINTN                     TimeoutInMicroseconds,
433   IN  VOID                      *ProcedureArgument      OPTIONAL,
434   OUT UINTN                     **FailedCpuList         OPTIONAL
435   )
436 {
437   if (WaitEvent != NULL) {
438     return EFI_UNSUPPORTED;
439   }
440 
441   return StartupAllAPsWorker (
442            Procedure,
443            SingleThread,
444            NULL,
445            TimeoutInMicroseconds,
446            ProcedureArgument,
447            FailedCpuList
448            );
449 }
450 
451 /**
452   This service lets the caller get one enabled AP to execute a caller-provided
453   function.
454 
455   @param[in]  Procedure               A pointer to the function to be run on the
456                                       designated AP of the system. See type
457                                       EFI_AP_PROCEDURE.
458   @param[in]  ProcessorNumber         The handle number of the AP. The range is
459                                       from 0 to the total number of logical
460                                       processors minus 1. The total number of
461                                       logical processors can be retrieved by
462                                       MpInitLibGetNumberOfProcessors().
463   @param[in]  WaitEvent               The event created by the caller with CreateEvent()
464                                       service.  If it is NULL, then execute in
465                                       blocking mode. BSP waits until this AP finish
466                                       or TimeoutInMicroSeconds expires.  If it's
467                                       not NULL, then execute in non-blocking mode.
468                                       BSP requests the function specified by
469                                       Procedure to be started on this AP,
470                                       and go on executing immediately. If this AP
471                                       return from Procedure or TimeoutInMicroSeconds
472                                       expires, this event is signaled. The BSP
473                                       can use the CheckEvent() or WaitForEvent()
474                                       services to check the state of event.  Type
475                                       EFI_EVENT is defined in CreateEvent() in
476                                       the Unified Extensible Firmware Interface
477                                       Specification.
478   @param[in]  TimeoutInMicroseconds   Indicates the time limit in microseconds for
479                                       this AP to finish this Procedure, either for
480                                       blocking or non-blocking mode. Zero means
481                                       infinity.  If the timeout expires before
482                                       this AP returns from Procedure, then Procedure
483                                       on the AP is terminated. The
484                                       AP is available for next function assigned
485                                       by MpInitLibStartupAllAPs() or
486                                       MpInitLibStartupThisAP().
487                                       If the timeout expires in blocking mode,
488                                       BSP returns EFI_TIMEOUT.  If the timeout
489                                       expires in non-blocking mode, WaitEvent
490                                       is signaled with SignalEvent().
491   @param[in]  ProcedureArgument       The parameter passed into Procedure on the
492                                       specified AP.
493   @param[out] Finished                If NULL, this parameter is ignored.  In
494                                       blocking mode, this parameter is ignored.
495                                       In non-blocking mode, if AP returns from
496                                       Procedure before the timeout expires, its
497                                       content is set to TRUE. Otherwise, the
498                                       value is set to FALSE. The caller can
499                                       determine if the AP returned from Procedure
500                                       by evaluating this value.
501 
502   @retval EFI_SUCCESS             In blocking mode, specified AP finished before
503                                   the timeout expires.
504   @retval EFI_SUCCESS             In non-blocking mode, the function has been
505                                   dispatched to specified AP.
506   @retval EFI_UNSUPPORTED         A non-blocking mode request was made after the
507                                   UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was
508                                   signaled.
509   @retval EFI_UNSUPPORTED         WaitEvent is not NULL if non-blocking mode is not
510                                   supported.
511   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
512   @retval EFI_TIMEOUT             In blocking mode, the timeout expired before
513                                   the specified AP has finished.
514   @retval EFI_NOT_READY           The specified AP is busy.
515   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
516   @retval EFI_NOT_FOUND           The processor with the handle specified by
517                                   ProcessorNumber does not exist.
518   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP or disabled AP.
519   @retval EFI_INVALID_PARAMETER   Procedure is NULL.
520 
521 **/
522 EFI_STATUS
523 EFIAPI
MpInitLibStartupThisAP(IN EFI_AP_PROCEDURE Procedure,IN UINTN ProcessorNumber,IN EFI_EVENT WaitEvent OPTIONAL,IN UINTN TimeoutInMicroseconds,IN VOID * ProcedureArgument OPTIONAL,OUT BOOLEAN * Finished OPTIONAL)524 MpInitLibStartupThisAP (
525   IN  EFI_AP_PROCEDURE          Procedure,
526   IN  UINTN                     ProcessorNumber,
527   IN  EFI_EVENT                 WaitEvent               OPTIONAL,
528   IN  UINTN                     TimeoutInMicroseconds,
529   IN  VOID                      *ProcedureArgument      OPTIONAL,
530   OUT BOOLEAN                   *Finished               OPTIONAL
531   )
532 {
533   if (WaitEvent != NULL) {
534     return EFI_UNSUPPORTED;
535   }
536 
537   return StartupThisAPWorker (
538            Procedure,
539            ProcessorNumber,
540            NULL,
541            TimeoutInMicroseconds,
542            ProcedureArgument,
543            Finished
544            );
545 }
546 
547 /**
548   This service switches the requested AP to be the BSP from that point onward.
549   This service changes the BSP for all purposes. This call can only be performed
550   by the current BSP.
551 
552   @param[in] ProcessorNumber   The handle number of AP that is to become the new
553                                BSP. The range is from 0 to the total number of
554                                logical processors minus 1. The total number of
555                                logical processors can be retrieved by
556                                MpInitLibGetNumberOfProcessors().
557   @param[in] EnableOldBSP      If TRUE, then the old BSP will be listed as an
558                                enabled AP. Otherwise, it will be disabled.
559 
560   @retval EFI_SUCCESS             BSP successfully switched.
561   @retval EFI_UNSUPPORTED         Switching the BSP cannot be completed prior to
562                                   this service returning.
563   @retval EFI_UNSUPPORTED         Switching the BSP is not supported.
564   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
565   @retval EFI_NOT_FOUND           The processor with the handle specified by
566                                   ProcessorNumber does not exist.
567   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the current BSP or
568                                   a disabled AP.
569   @retval EFI_NOT_READY           The specified AP is busy.
570   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
571 
572 **/
573 EFI_STATUS
574 EFIAPI
MpInitLibSwitchBSP(IN UINTN ProcessorNumber,IN BOOLEAN EnableOldBSP)575 MpInitLibSwitchBSP (
576   IN UINTN                     ProcessorNumber,
577   IN  BOOLEAN                  EnableOldBSP
578   )
579 {
580   return SwitchBSPWorker (ProcessorNumber, EnableOldBSP);
581 }
582 
583 /**
584   This service lets the caller enable or disable an AP from this point onward.
585   This service may only be called from the BSP.
586 
587   @param[in] ProcessorNumber   The handle number of AP.
588                                The range is from 0 to the total number of
589                                logical processors minus 1. The total number of
590                                logical processors can be retrieved by
591                                MpInitLibGetNumberOfProcessors().
592   @param[in] EnableAP          Specifies the new state for the processor for
593                                enabled, FALSE for disabled.
594   @param[in] HealthFlag        If not NULL, a pointer to a value that specifies
595                                the new health status of the AP. This flag
596                                corresponds to StatusFlag defined in
597                                EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only
598                                the PROCESSOR_HEALTH_STATUS_BIT is used. All other
599                                bits are ignored.  If it is NULL, this parameter
600                                is ignored.
601 
602   @retval EFI_SUCCESS             The specified AP was enabled or disabled successfully.
603   @retval EFI_UNSUPPORTED         Enabling or disabling an AP cannot be completed
604                                   prior to this service returning.
605   @retval EFI_UNSUPPORTED         Enabling or disabling an AP is not supported.
606   @retval EFI_DEVICE_ERROR        The calling processor is an AP.
607   @retval EFI_NOT_FOUND           Processor with the handle specified by ProcessorNumber
608                                   does not exist.
609   @retval EFI_INVALID_PARAMETER   ProcessorNumber specifies the BSP.
610   @retval EFI_NOT_READY           MP Initialize Library is not initialized.
611 
612 **/
613 EFI_STATUS
614 EFIAPI
MpInitLibEnableDisableAP(IN UINTN ProcessorNumber,IN BOOLEAN EnableAP,IN UINT32 * HealthFlag OPTIONAL)615 MpInitLibEnableDisableAP (
616   IN  UINTN                     ProcessorNumber,
617   IN  BOOLEAN                   EnableAP,
618   IN  UINT32                    *HealthFlag OPTIONAL
619   )
620 {
621   return EnableDisableApWorker (ProcessorNumber, EnableAP, HealthFlag);
622 }
623 
624 
625