]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/MpServicesOnFrameworkMpServicesThunk/MpServicesOnFrameworkMpServicesThunk.c
EdkCompatibilityPkg: Remove EdkCompatibilityPkg
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / MpServicesOnFrameworkMpServicesThunk / MpServicesOnFrameworkMpServicesThunk.c
diff --git a/EdkCompatibilityPkg/Compatibility/MpServicesOnFrameworkMpServicesThunk/MpServicesOnFrameworkMpServicesThunk.c b/EdkCompatibilityPkg/Compatibility/MpServicesOnFrameworkMpServicesThunk/MpServicesOnFrameworkMpServicesThunk.c
deleted file mode 100644 (file)
index 73c89a1..0000000
+++ /dev/null
@@ -1,1637 +0,0 @@
-/** @file\r
-Produces PI MP Services Protocol on top of Framework MP Services Protocol.\r
-\r
-Intel's Framework MP Services Protocol is replaced by EFI_MP_SERVICES_PROTOCOL in PI 1.1.\r
-This module produces PI MP Services Protocol on top of Framework MP Services Protocol.\r
-\r
-Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-Module Name:\r
-\r
-**/\r
-\r
-#include "MpServicesOnFrameworkMpServicesThunk.h"\r
-\r
-EFI_HANDLE                          mHandle = NULL;\r
-MP_SYSTEM_DATA                      mMPSystemData;\r
-EFI_PHYSICAL_ADDRESS                mStartupVector;\r
-MP_CPU_EXCHANGE_INFO                *mExchangeInfo;\r
-BOOLEAN                             mStopCheckAPsStatus = FALSE;\r
-UINTN                               mNumberOfProcessors;\r
-EFI_GENERIC_MEMORY_TEST_PROTOCOL    *mGenMemoryTest;\r
-\r
-FRAMEWORK_EFI_MP_SERVICES_PROTOCOL  *mFrameworkMpService;\r
-EFI_MP_SERVICES_PROTOCOL            mMpService = {\r
-  GetNumberOfProcessors,\r
-  GetProcessorInfo,\r
-  StartupAllAPs,\r
-  StartupThisAP,\r
-  SwitchBSP,\r
-  EnableDisableAP,\r
-  WhoAmI\r
-};\r
-\r
-\r
-/**\r
-  Implementation of GetNumberOfProcessors() service of MP Services Protocol.\r
-\r
-  This service retrieves the number of logical processor in the platform\r
-  and the number of those logical processors that are enabled on this boot.\r
-  This service may only be called from the BSP.\r
-\r
-  @param  This                       A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
-  @param  NumberOfProcessors         Pointer to the total number of logical processors in the system,\r
-                                     including the BSP and disabled APs.\r
-  @param  NumberOfEnabledProcessors  Pointer to the number of enabled logical processors that exist\r
-                                     in system, including the BSP.\r
-\r
-  @retval EFI_SUCCESS               Number of logical processors and enabled logical processors retrieved..\r
-  @retval EFI_DEVICE_ERROR           Caller processor is AP.\r
-  @retval EFI_INVALID_PARAMETER      NumberOfProcessors is NULL\r
-  @retval EFI_INVALID_PARAMETER      NumberOfEnabledProcessors is NULL\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-GetNumberOfProcessors (\r
-  IN  EFI_MP_SERVICES_PROTOCOL     *This,\r
-  OUT UINTN                        *NumberOfProcessors,\r
-  OUT UINTN                        *NumberOfEnabledProcessors\r
-  )\r
-{\r
-  EFI_STATUS      Status;\r
-  UINTN           CallerNumber;\r
-\r
-  //\r
-  // Check whether caller processor is BSP\r
-  //\r
-  WhoAmI (This, &CallerNumber);\r
-  if (CallerNumber != GetBspNumber ()) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Check parameter NumberOfProcessors\r
-  //\r
-  if (NumberOfProcessors == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // Check parameter NumberOfEnabledProcessors\r
-  //\r
-  if (NumberOfEnabledProcessors == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Status = mFrameworkMpService->GetGeneralMPInfo (\r
-                                  mFrameworkMpService,\r
-                                  NumberOfProcessors,\r
-                                  NULL,\r
-                                  NumberOfEnabledProcessors,\r
-                                  NULL,\r
-                                  NULL\r
-                                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Implementation of GetNumberOfProcessors() service of MP Services Protocol.\r
-\r
-  Gets detailed MP-related information on the requested processor at the\r
-  instant this call is made. This service may only be called from the BSP.\r
-\r
-  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
-  @param  ProcessorNumber       The handle number of processor.\r
-  @param  ProcessorInfoBuffer   A pointer to the buffer where information for the requested processor is deposited.\r
-\r
-  @retval EFI_SUCCESS           Processor information successfully returned.\r
-  @retval EFI_DEVICE_ERROR      Caller processor is AP.\r
-  @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL\r
-  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-GetProcessorInfo (\r
-  IN       EFI_MP_SERVICES_PROTOCOL     *This,\r
-  IN       UINTN                        ProcessorNumber,\r
-  OUT      EFI_PROCESSOR_INFORMATION    *ProcessorInfoBuffer\r
-  )\r
-{\r
-  EFI_STATUS                 Status;\r
-  UINTN                      CallerNumber;\r
-  UINTN                      BufferSize;\r
-  EFI_MP_PROC_CONTEXT        ProcessorContextBuffer;\r
-\r
-  //\r
-  // Check whether caller processor is BSP\r
-  //\r
-  WhoAmI (This, &CallerNumber);\r
-  if (CallerNumber != GetBspNumber ()) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Check parameter ProcessorInfoBuffer\r
-  //\r
-  if (ProcessorInfoBuffer == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // Check whether processor with the handle specified by ProcessorNumber exists\r
-  //\r
-  if (ProcessorNumber >= mNumberOfProcessors) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  BufferSize = sizeof (EFI_MP_PROC_CONTEXT);\r
-  Status = mFrameworkMpService->GetProcessorContext (\r
-                                  mFrameworkMpService,\r
-                                  ProcessorNumber,\r
-                                  &BufferSize,\r
-                                  &ProcessorContextBuffer\r
-                                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  ProcessorInfoBuffer->ProcessorId = (UINT64) ProcessorContextBuffer.ApicID;\r
-\r
-  //\r
-  // Get Status Flag of specified processor\r
-  //\r
-  ProcessorInfoBuffer->StatusFlag = 0;\r
-\r
-  if (ProcessorContextBuffer.Enabled) {\r
-    ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;\r
-  }\r
-\r
-  if (ProcessorContextBuffer.Designation == EfiCpuBSP) {\r
-    ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;\r
-  }\r
-\r
-  if (ProcessorContextBuffer.Health.Flags.Uint32 == 0) {\r
-    ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;\r
-  }\r
-\r
-  ProcessorInfoBuffer->Location.Package = (UINT32) ProcessorContextBuffer.PackageNumber;\r
-  ProcessorInfoBuffer->Location.Core    = (UINT32) ProcessorContextBuffer.NumberOfCores;\r
-  ProcessorInfoBuffer->Location.Thread  = (UINT32) ProcessorContextBuffer.NumberOfThreads;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Implementation of StartupAllAPs() service of MP Services Protocol.\r
-\r
-  This service lets the caller get all enabled APs to execute a caller-provided function.\r
-  This service may only be called from the BSP.\r
-\r
-  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
-  @param  Procedure             A pointer to the function to be run on enabled APs of the system.\r
-  @param  SingleThread          Indicates whether to execute the function simultaneously or one by one..\r
-  @param  WaitEvent             The event created by the caller.\r
-                                If it is NULL, then execute in blocking mode.\r
-                                If it is not NULL, then execute in non-blocking mode.\r
-  @param  TimeoutInMicroSeconds The time limit in microseconds for this AP to finish the function.\r
-                                Zero means infinity.\r
-  @param  ProcedureArgument     Pointer to the optional parameter of the assigned function.\r
-  @param  FailedCpuList         The list of processor numbers that fail to finish the function before\r
-                                TimeoutInMicrosecsond expires.\r
-\r
-  @retval EFI_SUCCESS           In blocking mode, all APs have finished before the timeout expired.\r
-  @retval EFI_SUCCESS           In non-blocking mode, function has been dispatched to all enabled APs.\r
-  @retval EFI_DEVICE_ERROR      Caller processor is AP.\r
-  @retval EFI_NOT_STARTED       No enabled AP exists in the system.\r
-  @retval EFI_NOT_READY         Any enabled AP is busy.\r
-  @retval EFI_TIMEOUT           In blocking mode, The timeout expired before all enabled APs have finished.\r
-  @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-StartupAllAPs (\r
-  IN  EFI_MP_SERVICES_PROTOCOL   *This,\r
-  IN  EFI_AP_PROCEDURE           Procedure,\r
-  IN  BOOLEAN                    SingleThread,\r
-  IN  EFI_EVENT                  WaitEvent             OPTIONAL,\r
-  IN  UINTN                      TimeoutInMicroSeconds,\r
-  IN  VOID                       *ProcedureArgument    OPTIONAL,\r
-  OUT UINTN                      **FailedCpuList       OPTIONAL\r
-  )\r
-{\r
-  EFI_STATUS      Status;\r
-  UINTN           ProcessorNumber;\r
-  CPU_DATA_BLOCK  *CpuData;\r
-  BOOLEAN         Blocking;\r
-  UINTN           BspNumber;\r
-\r
-  if (FailedCpuList != NULL) {\r
-    *FailedCpuList = NULL;\r
-  }\r
-\r
-  //\r
-  // Check whether caller processor is BSP\r
-  //\r
-  BspNumber = GetBspNumber ();\r
-  WhoAmI (This, &ProcessorNumber);\r
-  if (ProcessorNumber != BspNumber) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Check parameter Procedure\r
-  //\r
-  if (Procedure == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // Temporarily suppress CheckAPsStatus()\r
-  //\r
-  mStopCheckAPsStatus = TRUE;\r
-\r
-  //\r
-  // Check whether all enabled APs are idle.\r
-  // If any enabled AP is not idle, return EFI_NOT_READY.\r
-  //\r
-  for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {\r
-\r
-    CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-    mMPSystemData.CpuList[ProcessorNumber] = FALSE;\r
-    if (ProcessorNumber != BspNumber) {\r
-      if (CpuData->State != CpuStateDisabled) {\r
-        if (CpuData->State != CpuStateIdle) {\r
-          mStopCheckAPsStatus = FALSE;\r
-          return EFI_NOT_READY;\r
-        } else {\r
-          //\r
-          // Mark this processor as responsible for current calling.\r
-          //\r
-          mMPSystemData.CpuList[ProcessorNumber] = TRUE;\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  mMPSystemData.FinishCount = 0;\r
-  mMPSystemData.StartCount  = 0;\r
-  Blocking                  = FALSE;\r
-  //\r
-  // Go through all enabled APs to wakeup them for Procedure.\r
-  // If in Single Thread mode, then only one AP is woken up, and others are waiting.\r
-  //\r
-  for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {\r
-\r
-    CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-    //\r
-    // Check whether this processor is responsible for current calling.\r
-    //\r
-    if (mMPSystemData.CpuList[ProcessorNumber]) {\r
-\r
-      mMPSystemData.StartCount++;\r
-\r
-      AcquireSpinLock (&CpuData->CpuDataLock);\r
-      CpuData->State = CpuStateReady;\r
-      ReleaseSpinLock (&CpuData->CpuDataLock);\r
-\r
-      if (!Blocking) {\r
-        WakeUpAp (\r
-          ProcessorNumber,\r
-          Procedure,\r
-          ProcedureArgument\r
-          );\r
-      }\r
-\r
-      if (SingleThread) {\r
-        Blocking = TRUE;\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  // If no enabled AP exists, return EFI_NOT_STARTED.\r
-  //\r
-  if (mMPSystemData.StartCount == 0) {\r
-    mStopCheckAPsStatus = FALSE;\r
-    return EFI_NOT_STARTED;\r
-  }\r
-\r
-  //\r
-  // If WaitEvent is not NULL, execute in non-blocking mode.\r
-  // BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS.\r
-  // CheckAPsStatus() will check completion and timeout periodically.\r
-  //\r
-  mMPSystemData.Procedure      = Procedure;\r
-  mMPSystemData.ProcArguments  = ProcedureArgument;\r
-  mMPSystemData.SingleThread   = SingleThread;\r
-  mMPSystemData.FailedCpuList  = FailedCpuList;\r
-  mMPSystemData.ExpectedTime   = CalculateTimeout (TimeoutInMicroSeconds, &mMPSystemData.CurrentTime);\r
-  mMPSystemData.WaitEvent      = WaitEvent;\r
-\r
-  //\r
-  // Allow CheckAPsStatus()\r
-  //\r
-  mStopCheckAPsStatus = FALSE;\r
-\r
-  if (WaitEvent != NULL) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // If WaitEvent is NULL, execute in blocking mode.\r
-  // BSP checks APs'state until all APs finish or TimeoutInMicrosecsond expires.\r
-  //\r
-  do {\r
-    Status = CheckAllAPs ();\r
-  } while (Status == EFI_NOT_READY);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Implementation of StartupThisAP() service of MP Services Protocol.\r
-\r
-  This service lets the caller get one enabled AP to execute a caller-provided function.\r
-  This service may only be called from the BSP.\r
-\r
-  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
-  @param  Procedure             A pointer to the function to be run on the designated AP.\r
-  @param  ProcessorNumber       The handle number of AP..\r
-  @param  WaitEvent             The event created by the caller.\r
-                                If it is NULL, then execute in blocking mode.\r
-                                If it is not NULL, then execute in non-blocking mode.\r
-  @param  TimeoutInMicroseconds The time limit in microseconds for this AP to finish the function.\r
-                                Zero means infinity.\r
-  @param  ProcedureArgument     Pointer to the optional parameter of the assigned function.\r
-  @param  Finished              Indicates whether AP has finished assigned function.\r
-                                In blocking mode, it is ignored.\r
-\r
-  @retval EFI_SUCCESS           In blocking mode, specified AP has finished before the timeout expires.\r
-  @retval EFI_SUCCESS           In non-blocking mode, function has been dispatched to specified AP.\r
-  @retval EFI_DEVICE_ERROR      Caller processor is AP.\r
-  @retval EFI_TIMEOUT           In blocking mode, the timeout expires before specified AP has finished.\r
-  @retval EFI_NOT_READY         Specified AP is busy.\r
-  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.\r
-  @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.\r
-  @retval EFI_INVALID_PARAMETER Procedure is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-StartupThisAP (\r
-  IN  EFI_MP_SERVICES_PROTOCOL   *This,\r
-  IN  EFI_AP_PROCEDURE           Procedure,\r
-  IN  UINTN                      ProcessorNumber,\r
-  IN  EFI_EVENT                  WaitEvent OPTIONAL,\r
-  IN  UINTN                      TimeoutInMicroseconds,\r
-  IN  VOID                       *ProcedureArgument OPTIONAL,\r
-  OUT BOOLEAN                    *Finished OPTIONAL\r
-  )\r
-{\r
-  CPU_DATA_BLOCK  *CpuData;\r
-  UINTN           CallerNumber;\r
-  EFI_STATUS      Status;\r
-  UINTN           BspNumber;\r
-\r
-  if (Finished != NULL) {\r
-    *Finished = TRUE;\r
-  }\r
-\r
-  //\r
-  // Check whether caller processor is BSP\r
-  //\r
-  BspNumber = GetBspNumber ();\r
-  WhoAmI (This, &CallerNumber);\r
-  if (CallerNumber != BspNumber) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Check whether processor with the handle specified by ProcessorNumber exists\r
-  //\r
-  if (ProcessorNumber >= mNumberOfProcessors) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // Check whether specified processor is BSP\r
-  //\r
-  if (ProcessorNumber == BspNumber) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // Check parameter Procedure\r
-  //\r
-  if (Procedure == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-  //\r
-  // Temporarily suppress CheckAPsStatus()\r
-  //\r
-  mStopCheckAPsStatus = TRUE;\r
-\r
-  //\r
-  // Check whether specified AP is disabled\r
-  //\r
-  if (CpuData->State == CpuStateDisabled) {\r
-    mStopCheckAPsStatus = FALSE;\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // Check whether specified AP is busy\r
-  //\r
-  if (CpuData->State != CpuStateIdle) {\r
-    mStopCheckAPsStatus = FALSE;\r
-    return EFI_NOT_READY;\r
-  }\r
-\r
-  //\r
-  // Wakeup specified AP for Procedure.\r
-  //\r
-  AcquireSpinLock (&CpuData->CpuDataLock);\r
-  CpuData->State = CpuStateReady;\r
-  ReleaseSpinLock (&CpuData->CpuDataLock);\r
-\r
-  WakeUpAp (\r
-    ProcessorNumber,\r
-    Procedure,\r
-    ProcedureArgument\r
-    );\r
-\r
-  //\r
-  // If WaitEvent is not NULL, execute in non-blocking mode.\r
-  // BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS.\r
-  // CheckAPsStatus() will check completion and timeout periodically.\r
-  //\r
-  CpuData->WaitEvent      = WaitEvent;\r
-  CpuData->Finished       = Finished;\r
-  CpuData->ExpectedTime   = CalculateTimeout (TimeoutInMicroseconds, &CpuData->CurrentTime);\r
-\r
-  //\r
-  // Allow CheckAPsStatus()\r
-  //\r
-  mStopCheckAPsStatus = FALSE;\r
-\r
-  if (WaitEvent != NULL) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // If WaitEvent is NULL, execute in blocking mode.\r
-  // BSP checks AP's state until it finishes or TimeoutInMicrosecsond expires.\r
-  //\r
-  do {\r
-    Status = CheckThisAP (ProcessorNumber);\r
-  } while (Status == EFI_NOT_READY);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Implementation of SwitchBSP() service of MP Services Protocol.\r
-\r
-  This service switches the requested AP to be the BSP from that point onward.\r
-  This service may only be called from the current BSP.\r
-\r
-  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
-  @param  ProcessorNumber       The handle number of processor.\r
-  @param  EnableOldBSP          Whether to enable or disable the original BSP.\r
-\r
-  @retval EFI_SUCCESS           BSP successfully switched.\r
-  @retval EFI_DEVICE_ERROR      Caller processor is AP.\r
-  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.\r
-  @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.\r
-  @retval EFI_NOT_READY         Specified AP is busy.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SwitchBSP (\r
-  IN  EFI_MP_SERVICES_PROTOCOL            *This,\r
-  IN  UINTN                               ProcessorNumber,\r
-  IN  BOOLEAN                             EnableOldBSP\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  CPU_DATA_BLOCK        *CpuData;\r
-  UINTN                 CallerNumber;\r
-  UINTN                 BspNumber;\r
-  UINTN                 ApicBase;\r
-  UINT32                CurrentTimerValue;\r
-  UINT32                CurrentTimerRegister;\r
-  UINT32                CurrentTimerDivide;\r
-  UINT64                CurrentTscValue;\r
-  BOOLEAN               OldInterruptState;\r
-\r
-  //\r
-  // Check whether caller processor is BSP\r
-  //\r
-  BspNumber = GetBspNumber ();\r
-  WhoAmI (This, &CallerNumber);\r
-  if (CallerNumber != BspNumber) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Check whether processor with the handle specified by ProcessorNumber exists\r
-  //\r
-  if (ProcessorNumber >= mNumberOfProcessors) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // Check whether specified processor is BSP\r
-  //\r
-  if (ProcessorNumber == BspNumber) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-  //\r
-  // Check whether specified AP is disabled\r
-  //\r
-  if (CpuData->State == CpuStateDisabled) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // Check whether specified AP is busy\r
-  //\r
-  if (CpuData->State != CpuStateIdle) {\r
-    return EFI_NOT_READY;\r
-  }\r
-\r
-  //\r
-  // Save and disable interrupt.\r
-  //\r
-  OldInterruptState = SaveAndDisableInterrupts ();\r
-       \r
-  //\r
-  // Record the current local APIC timer setting of BSP\r
-  //\r
-  ApicBase = (UINTN)AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE, 12, 35) << 12;\r
-  CurrentTimerValue     = MmioRead32 (ApicBase + APIC_REGISTER_TIMER_COUNT);\r
-  CurrentTimerRegister  = MmioRead32 (ApicBase + APIC_REGISTER_LVT_TIMER);\r
-  CurrentTimerDivide    = MmioRead32 (ApicBase + APIC_REGISTER_TIMER_DIVIDE);\r
-  //\r
-  // Set mask bit (BIT 16) of LVT Timer Register to disable its interrupt\r
-  //\r
-  MmioBitFieldWrite32 (ApicBase + APIC_REGISTER_LVT_TIMER, 16, 16, 1);\r
-\r
-  //\r
-  // Record the current TSC value\r
-  //\r
-  CurrentTscValue = AsmReadTsc ();\r
-  \r
-  Status = mFrameworkMpService->SwitchBSP (\r
-                                  mFrameworkMpService,\r
-                                  ProcessorNumber,\r
-                                  EnableOldBSP\r
-                                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Restore TSC value\r
-  //\r
-  AsmWriteMsr64 (MSR_IA32_TIME_STAMP_COUNTER, CurrentTscValue);\r
-\r
-  //\r
-  // Restore local APIC timer setting to new BSP\r
-  //\r
-  MmioWrite32 (ApicBase + APIC_REGISTER_TIMER_DIVIDE, CurrentTimerDivide);\r
-  MmioWrite32 (ApicBase + APIC_REGISTER_TIMER_INIT_COUNT, CurrentTimerValue);\r
-  MmioWrite32 (ApicBase + APIC_REGISTER_LVT_TIMER, CurrentTimerRegister);\r
-\r
-  //\r
-  // Restore interrupt state.\r
-  //\r
-  SetInterruptState (OldInterruptState);\r
-  \r
-  ChangeCpuState (BspNumber, EnableOldBSP);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Implementation of EnableDisableAP() service of MP Services Protocol.\r
-\r
-  This service lets the caller enable or disable an AP.\r
-  This service may only be called from the BSP.\r
-\r
-  @param  This                   A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
-  @param  ProcessorNumber        The handle number of processor.\r
-  @param  EnableAP               Indicates whether the newstate of the AP is enabled or disabled.\r
-  @param  HealthFlag             Indicates new health state of the AP..\r
-\r
-  @retval EFI_SUCCESS            AP successfully enabled or disabled.\r
-  @retval EFI_DEVICE_ERROR       Caller processor is AP.\r
-  @retval EFI_NOT_FOUND          Processor with the handle specified by ProcessorNumber does not exist.\r
-  @retval EFI_INVALID_PARAMETERS ProcessorNumber specifies the BSP.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EnableDisableAP (\r
-  IN  EFI_MP_SERVICES_PROTOCOL            *This,\r
-  IN  UINTN                               ProcessorNumber,\r
-  IN  BOOLEAN                             EnableAP,\r
-  IN  UINT32                              *HealthFlag OPTIONAL\r
-  )\r
-{\r
-  EFI_STATUS      Status;\r
-  UINTN           CallerNumber;\r
-  EFI_MP_HEALTH   HealthState;\r
-  EFI_MP_HEALTH   *HealthStatePointer;\r
-  UINTN           BspNumber;\r
-\r
-  //\r
-  // Check whether caller processor is BSP\r
-  //\r
-  BspNumber = GetBspNumber ();\r
-  WhoAmI (This, &CallerNumber);\r
-  if (CallerNumber != BspNumber) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Check whether processor with the handle specified by ProcessorNumber exists\r
-  //\r
-  if (ProcessorNumber >= mNumberOfProcessors) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // Check whether specified processor is BSP\r
-  //\r
-  if (ProcessorNumber == BspNumber) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (HealthFlag == NULL) {\r
-    HealthStatePointer = NULL;\r
-  } else {\r
-    if ((*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT) == 0) {\r
-      HealthState.Flags.Uint32 = 1;\r
-    } else {\r
-      HealthState.Flags.Uint32 = 0;\r
-    }\r
-    HealthState.TestStatus = 0;\r
-\r
-    HealthStatePointer = &HealthState;\r
-  }\r
-\r
-  Status = mFrameworkMpService->EnableDisableAP (\r
-                                  mFrameworkMpService,\r
-                                  ProcessorNumber,\r
-                                  EnableAP,\r
-                                  HealthStatePointer\r
-                                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  ChangeCpuState (ProcessorNumber, EnableAP);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Implementation of WhoAmI() service of MP Services Protocol.\r
-\r
-  This service lets the caller processor get its handle number.\r
-  This service may be called from the BSP and APs.\r
-\r
-  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.\r
-  @param  ProcessorNumber       Pointer to the handle number of AP.\r
-\r
-  @retval EFI_SUCCESS           Processor number successfully returned.\r
-  @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-WhoAmI (\r
-  IN  EFI_MP_SERVICES_PROTOCOL            *This,\r
-  OUT UINTN                               *ProcessorNumber\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-\r
-  if (ProcessorNumber == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Status = mFrameworkMpService->WhoAmI (\r
-                                  mFrameworkMpService,\r
-                                  ProcessorNumber\r
-                                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Checks APs' status periodically.\r
-\r
-  This function is triggered by timer periodically to check the\r
-  state of APs for StartupAllAPs() and StartupThisAP() executed\r
-  in non-blocking mode.\r
-\r
-  @param  Event    Event triggered.\r
-  @param  Context  Parameter passed with the event.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-CheckAPsStatus (\r
-  IN  EFI_EVENT                           Event,\r
-  IN  VOID                                *Context\r
-  )\r
-{\r
-  UINTN           ProcessorNumber;\r
-  CPU_DATA_BLOCK  *CpuData;\r
-  EFI_STATUS      Status;\r
-\r
-  //\r
-  // If CheckAPsStatus() is stopped, then return immediately.\r
-  //\r
-  if (mStopCheckAPsStatus) {\r
-    return;\r
-  }\r
-\r
-  //\r
-  // First, check whether pending StartupAllAPs() exists.\r
-  //\r
-  if (mMPSystemData.WaitEvent != NULL) {\r
-\r
-    Status = CheckAllAPs ();\r
-    //\r
-    // If all APs finish for StartupAllAPs(), signal the WaitEvent for it..\r
-    //\r
-    if (Status != EFI_NOT_READY) {\r
-      Status = gBS->SignalEvent (mMPSystemData.WaitEvent);\r
-      mMPSystemData.WaitEvent = NULL;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Second, check whether pending StartupThisAPs() callings exist.\r
-  //\r
-  for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {\r
-\r
-    CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-    if (CpuData->WaitEvent == NULL) {\r
-      continue;\r
-    }\r
-\r
-    Status = CheckThisAP (ProcessorNumber);\r
-\r
-    if (Status != EFI_NOT_READY) {\r
-      gBS->SignalEvent (CpuData->WaitEvent);\r
-      CpuData->WaitEvent = NULL;\r
-    }\r
-  }\r
-  return ;\r
-}\r
-\r
-/**\r
-  Checks status of all APs.\r
-\r
-  This function checks whether all APs have finished task assigned by StartupAllAPs(),\r
-  and whether timeout expires.\r
-\r
-  @retval EFI_SUCCESS           All APs have finished task assigned by StartupAllAPs().\r
-  @retval EFI_TIMEOUT           The timeout expires.\r
-  @retval EFI_NOT_READY         APs have not finished task and timeout has not expired.\r
-\r
-**/\r
-EFI_STATUS\r
-CheckAllAPs (\r
-  VOID\r
-  )\r
-{\r
-  UINTN           ProcessorNumber;\r
-  UINTN           NextProcessorNumber;\r
-  UINTN           ListIndex;\r
-  EFI_STATUS      Status;\r
-  CPU_STATE       CpuState;\r
-  CPU_DATA_BLOCK  *CpuData;\r
-\r
-  NextProcessorNumber = 0;\r
-\r
-  //\r
-  // Go through all APs that are responsible for the StartupAllAPs().\r
-  //\r
-  for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {\r
-    if (!mMPSystemData.CpuList[ProcessorNumber]) {\r
-      continue;\r
-    }\r
-\r
-    CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-    //\r
-    //  Check the CPU state of AP. If it is CpuStateFinished, then the AP has finished its task.\r
-    //  Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the\r
-    //  value of state after setting the it to CpuStateFinished, so BSP can safely make use of its value.\r
-    //\r
-    AcquireSpinLock (&CpuData->CpuDataLock);\r
-    CpuState = CpuData->State;\r
-    ReleaseSpinLock (&CpuData->CpuDataLock);\r
-\r
-    if (CpuState == CpuStateFinished) {\r
-      mMPSystemData.FinishCount++;\r
-      mMPSystemData.CpuList[ProcessorNumber] = FALSE;\r
-\r
-      AcquireSpinLock (&CpuData->CpuDataLock);\r
-      CpuData->State = CpuStateIdle;\r
-      ReleaseSpinLock (&CpuData->CpuDataLock);\r
-\r
-      //\r
-      // If in Single Thread mode, then search for the next waiting AP for execution.\r
-      //\r
-      if (mMPSystemData.SingleThread) {\r
-        Status = GetNextWaitingProcessorNumber (&NextProcessorNumber);\r
-\r
-        if (!EFI_ERROR (Status)) {\r
-          WakeUpAp (\r
-            NextProcessorNumber,\r
-            mMPSystemData.Procedure,\r
-            mMPSystemData.ProcArguments\r
-            );\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  // If all APs finish, return EFI_SUCCESS.\r
-  //\r
-  if (mMPSystemData.FinishCount == mMPSystemData.StartCount) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // If timeout expires, report timeout.\r
-  //\r
-  if (CheckTimeout (&mMPSystemData.CurrentTime, &mMPSystemData.TotalTime, mMPSystemData.ExpectedTime)) {\r
-    //\r
-    // If FailedCpuList is not NULL, record all failed APs in it.\r
-    //\r
-    if (mMPSystemData.FailedCpuList != NULL) {\r
-      *mMPSystemData.FailedCpuList = AllocatePool ((mMPSystemData.StartCount - mMPSystemData.FinishCount + 1) * sizeof(UINTN));\r
-      ASSERT (*mMPSystemData.FailedCpuList != NULL);\r
-    }\r
-    ListIndex = 0;\r
-\r
-    for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {\r
-      //\r
-      // Check whether this processor is responsible for StartupAllAPs().\r
-      //\r
-      if (mMPSystemData.CpuList[ProcessorNumber]) {\r
-        //\r
-        // Reset failed APs to idle state\r
-        //\r
-        ResetProcessorToIdleState (ProcessorNumber);\r
-        mMPSystemData.CpuList[ProcessorNumber] = FALSE;\r
-        if (mMPSystemData.FailedCpuList != NULL) {\r
-          (*mMPSystemData.FailedCpuList)[ListIndex++] = ProcessorNumber;\r
-        }\r
-      }\r
-    }\r
-    if (mMPSystemData.FailedCpuList != NULL) {\r
-      (*mMPSystemData.FailedCpuList)[ListIndex] = END_OF_CPU_LIST;\r
-    }\r
-    return EFI_TIMEOUT;\r
-  }\r
-  return EFI_NOT_READY;\r
-}\r
-\r
-/**\r
-  Checks status of specified AP.\r
-\r
-  This function checks whether specified AP has finished task assigned by StartupThisAP(),\r
-  and whether timeout expires.\r
-\r
-  @param  ProcessorNumber       The handle number of processor.\r
-\r
-  @retval EFI_SUCCESS           Specified AP has finished task assigned by StartupThisAPs().\r
-  @retval EFI_TIMEOUT           The timeout expires.\r
-  @retval EFI_NOT_READY         Specified AP has not finished task and timeout has not expired.\r
-\r
-**/\r
-EFI_STATUS\r
-CheckThisAP (\r
-  UINTN  ProcessorNumber\r
-  )\r
-{\r
-  CPU_DATA_BLOCK  *CpuData;\r
-  CPU_STATE       CpuState;\r
-\r
-  ASSERT (ProcessorNumber < mNumberOfProcessors);\r
-  ASSERT (ProcessorNumber < MAX_CPU_NUMBER);\r
-\r
-  CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-  //\r
-  //  Check the CPU state of AP. If it is CpuStateFinished, then the AP has finished its task.\r
-  //  Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the\r
-  //  value of state after setting the it to CpuStateFinished, so BSP can safely make use of its value.\r
-  //\r
-  AcquireSpinLock (&CpuData->CpuDataLock);\r
-  CpuState = CpuData->State;\r
-  ReleaseSpinLock (&CpuData->CpuDataLock);\r
-\r
-  //\r
-  // If the APs finishes for StartupThisAP(), return EFI_SUCCESS.\r
-  //\r
-  if (CpuState == CpuStateFinished) {\r
-\r
-    AcquireSpinLock (&CpuData->CpuDataLock);\r
-    CpuData->State = CpuStateIdle;\r
-    ReleaseSpinLock (&CpuData->CpuDataLock);\r
-\r
-    if (CpuData->Finished != NULL) {\r
-      *(CpuData->Finished) = TRUE;\r
-    }\r
-    return EFI_SUCCESS;\r
-  } else {\r
-    //\r
-    // If timeout expires for StartupThisAP(), report timeout.\r
-    //\r
-    if (CheckTimeout (&CpuData->CurrentTime, &CpuData->TotalTime, CpuData->ExpectedTime)) {\r
-\r
-      if (CpuData->Finished != NULL) {\r
-        *(CpuData->Finished) = FALSE;\r
-      }\r
-      //\r
-      // Reset failed AP to idle state\r
-      //\r
-      ResetProcessorToIdleState (ProcessorNumber);\r
-\r
-      return EFI_TIMEOUT;\r
-    }\r
-  }\r
-  return EFI_NOT_READY;\r
-}\r
-\r
-/**\r
-  Calculate timeout value and return the current performance counter value.\r
-\r
-  Calculate the number of performance counter ticks required for a timeout.\r
-  If TimeoutInMicroseconds is 0, return value is also 0, which is recognized\r
-  as infinity.\r
-\r
-  @param  TimeoutInMicroseconds   Timeout value in microseconds.\r
-  @param  CurrentTime             Returns the current value of the performance counter.\r
-\r
-  @return Expected timestamp counter for timeout.\r
-          If TimeoutInMicroseconds is 0, return value is also 0, which is recognized\r
-          as infinity.\r
-\r
-**/\r
-UINT64\r
-CalculateTimeout (\r
-  IN  UINTN   TimeoutInMicroseconds,\r
-  OUT UINT64  *CurrentTime\r
-  )\r
-{\r
-  //\r
-  // Read the current value of the performance counter\r
-  //\r
-  *CurrentTime = GetPerformanceCounter ();\r
-\r
-  //\r
-  // If TimeoutInMicroseconds is 0, return value is also 0, which is recognized\r
-  // as infinity.\r
-  //\r
-  if (TimeoutInMicroseconds == 0) {\r
-    return 0;\r
-  }\r
-\r
-  //\r
-  // GetPerformanceCounterProperties () returns the timestamp counter's frequency\r
-  // in Hz. So multiply the return value with TimeoutInMicroseconds and then divide\r
-  // it by 1,000,000, to get the number of ticks for the timeout value.\r
-  //\r
-  return DivU64x32 (\r
-           MultU64x64 (\r
-             GetPerformanceCounterProperties (NULL, NULL),\r
-             TimeoutInMicroseconds\r
-             ),\r
-           1000000\r
-           );\r
-}\r
-\r
-/**\r
-  Checks whether timeout expires.\r
-\r
-  Check whether the number of ellapsed performance counter ticks required for a timeout condition\r
-  has been reached.  If Timeout is zero, which means infinity, return value is always FALSE.\r
-\r
-  @param  PreviousTime         On input, the value of the performance counter when it was last read.\r
-                               On output, the current value of the performance counter\r
-  @param  TotalTime            The total amount of ellapsed time in performance counter ticks.\r
-  @param  Timeout              The number of performance counter ticks required to reach a timeout condition.\r
-\r
-  @retval TRUE                 A timeout condition has been reached.\r
-  @retval FALSE                A timeout condition has not been reached.\r
-\r
-**/\r
-BOOLEAN\r
-CheckTimeout (\r
-  IN OUT UINT64  *PreviousTime,\r
-  IN     UINT64  *TotalTime,\r
-  IN     UINT64  Timeout\r
-  )\r
-{\r
-  UINT64  Start;\r
-  UINT64  End;\r
-  UINT64  CurrentTime;\r
-  INT64   Delta;\r
-  INT64   Cycle;\r
-\r
-  if (Timeout == 0) {\r
-    return FALSE;\r
-  }\r
-  GetPerformanceCounterProperties (&Start, &End);\r
-  Cycle = End - Start;\r
-  if (Cycle < 0) {\r
-    Cycle = -Cycle;\r
-  }\r
-  Cycle++;\r
-  CurrentTime = GetPerformanceCounter();\r
-  Delta = (INT64) (CurrentTime - *PreviousTime);\r
-  if (Start > End) {\r
-    Delta = -Delta;\r
-  }\r
-  if (Delta < 0) {\r
-    Delta += Cycle;\r
-  }\r
-  *TotalTime += Delta;\r
-  *PreviousTime = CurrentTime;\r
-  if (*TotalTime > Timeout) {\r
-    return TRUE;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Searches for the next waiting AP.\r
-\r
-  Search for the next AP that is put in waiting state by single-threaded StartupAllAPs().\r
-\r
-  @param  NextProcessorNumber  Pointer to the processor number of the next waiting AP.\r
-\r
-  @retval EFI_SUCCESS          The next waiting AP has been found.\r
-  @retval EFI_NOT_FOUND        No waiting AP exists.\r
-\r
-**/\r
-EFI_STATUS\r
-GetNextWaitingProcessorNumber (\r
-  OUT UINTN                               *NextProcessorNumber\r
-  )\r
-{\r
-  UINTN           ProcessorNumber;\r
-\r
-  for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {\r
-\r
-    if (mMPSystemData.CpuList[ProcessorNumber]) {\r
-      *NextProcessorNumber = ProcessorNumber;\r
-      return EFI_SUCCESS;\r
-    }\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-\r
-/**\r
-  Wrapper function for all procedures assigned to AP.\r
-\r
-  Wrapper function for all procedures assigned to AP via MP service protocol.\r
-  It controls states of AP and invokes assigned precedure.\r
-\r
-**/\r
-VOID\r
-ApProcWrapper (\r
-  VOID\r
-  )\r
-{\r
-  EFI_AP_PROCEDURE      Procedure;\r
-  VOID                  *Parameter;\r
-  UINTN                 ProcessorNumber;\r
-  CPU_DATA_BLOCK        *CpuData;\r
-\r
-  //\r
-  // Program virtual wire mode for AP, since it will be lost after AP wake up\r
-  //\r
-  ProgramVirtualWireMode ();\r
-  DisableLvtInterrupts ();\r
-\r
-  //\r
-  // Initialize Debug Agent to support source level debug on AP code.\r
-  //\r
-  InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP, NULL, NULL);\r
-\r
-  WhoAmI (&mMpService, &ProcessorNumber);\r
-  CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-  AcquireSpinLock (&CpuData->CpuDataLock);\r
-  CpuData->State = CpuStateBusy;\r
-  ReleaseSpinLock (&CpuData->CpuDataLock);\r
-\r
-  //\r
-  // Now let us check it out.\r
-  //\r
-  AcquireSpinLock (&CpuData->CpuDataLock);\r
-  Procedure = CpuData->Procedure;\r
-  Parameter = CpuData->Parameter;\r
-  ReleaseSpinLock (&CpuData->CpuDataLock);\r
-\r
-  if (Procedure != NULL) {\r
-\r
-    Procedure (Parameter);\r
-\r
-    //\r
-    // if BSP is switched to AP, it continue execute from here, but it carries register state\r
-    // of the old AP, so need to reload CpuData (might be stored in a register after compiler\r
-    // optimization) to make sure it points to the right data\r
-    //\r
-    WhoAmI (&mMpService, &ProcessorNumber);\r
-    CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-    AcquireSpinLock (&CpuData->CpuDataLock);\r
-    CpuData->Procedure = NULL;\r
-    ReleaseSpinLock (&CpuData->CpuDataLock);\r
-  }\r
-\r
-  AcquireSpinLock (&CpuData->CpuDataLock);\r
-  CpuData->State = CpuStateFinished;\r
-  ReleaseSpinLock (&CpuData->CpuDataLock);\r
-}\r
-\r
-/**\r
-  Function to wake up a specified AP and assign procedure to it.\r
-\r
-  @param  ProcessorNumber  Handle number of the specified processor.\r
-  @param  Procedure        Procedure to assign.\r
-  @param  ProcArguments    Argument for Procedure.\r
-\r
-**/\r
-VOID\r
-WakeUpAp (\r
-  IN   UINTN                 ProcessorNumber,\r
-  IN   EFI_AP_PROCEDURE      Procedure,\r
-  IN   VOID                  *ProcArguments\r
-  )\r
-{\r
-  EFI_STATUS                   Status;\r
-  CPU_DATA_BLOCK               *CpuData;\r
-  EFI_PROCESSOR_INFORMATION    ProcessorInfoBuffer;\r
-\r
-  ASSERT (ProcessorNumber < mNumberOfProcessors);\r
-  ASSERT (ProcessorNumber < MAX_CPU_NUMBER);\r
-\r
-  CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-  AcquireSpinLock (&CpuData->CpuDataLock);\r
-  CpuData->Parameter  = ProcArguments;\r
-  CpuData->Procedure  = Procedure;\r
-  ReleaseSpinLock (&CpuData->CpuDataLock);\r
-\r
-  Status = GetProcessorInfo (\r
-             &mMpService,\r
-             ProcessorNumber,\r
-             &ProcessorInfoBuffer\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  mExchangeInfo->ApFunction = (VOID *) (UINTN) ApProcWrapper;\r
-  mExchangeInfo->ProcessorNumber[ProcessorInfoBuffer.ProcessorId] = (UINT32) ProcessorNumber;\r
-  SendInitSipiSipi (\r
-    (UINT32) ProcessorInfoBuffer.ProcessorId,\r
-    (UINT32) (UINTN) mStartupVector\r
-    );\r
-}\r
-\r
-/**\r
-  Terminate AP's task and set it to idle state.\r
-\r
-  This function terminates AP's task due to timeout by sending INIT-SIPI,\r
-  and sends it to idle state.\r
-\r
-  @param  ProcessorNumber  Handle number of the specified processor.\r
-\r
-**/\r
-VOID\r
-ResetProcessorToIdleState (\r
-  UINTN      ProcessorNumber\r
-  )\r
-{\r
-  EFI_STATUS                   Status;\r
-  CPU_DATA_BLOCK               *CpuData;\r
-  EFI_PROCESSOR_INFORMATION    ProcessorInfoBuffer;\r
-\r
-  Status = GetProcessorInfo (\r
-             &mMpService,\r
-             ProcessorNumber,\r
-             &ProcessorInfoBuffer\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  mExchangeInfo->ApFunction = NULL;\r
-  mExchangeInfo->ProcessorNumber[ProcessorInfoBuffer.ProcessorId] = (UINT32) ProcessorNumber;\r
-  SendInitSipiSipi (\r
-    (UINT32) ProcessorInfoBuffer.ProcessorId,\r
-    (UINT32) (UINTN) mStartupVector\r
-    );\r
-\r
-  CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-  AcquireSpinLock (&CpuData->CpuDataLock);\r
-  CpuData->State = CpuStateIdle;\r
-  ReleaseSpinLock (&CpuData->CpuDataLock);\r
-}\r
-\r
-/**\r
-  Worker function of EnableDisableAP ()\r
-\r
-  Worker function of EnableDisableAP (). Changes state of specified processor.\r
-\r
-  @param  ProcessorNumber Processor number of specified AP.\r
-  @param  NewState        Desired state of the specified AP.\r
-\r
-  @retval EFI_SUCCESS     AP's state successfully changed.\r
-\r
-**/\r
-EFI_STATUS\r
-ChangeCpuState (\r
-  IN     UINTN                      ProcessorNumber,\r
-  IN     BOOLEAN                    NewState\r
-  )\r
-{\r
-  CPU_DATA_BLOCK  *CpuData;\r
-\r
-  ASSERT (ProcessorNumber < mNumberOfProcessors);\r
-  ASSERT (ProcessorNumber < MAX_CPU_NUMBER);\r
-\r
-  CpuData = &mMPSystemData.CpuData[ProcessorNumber];\r
-\r
-  if (!NewState) {\r
-    AcquireSpinLock (&CpuData->CpuDataLock);\r
-    CpuData->State = CpuStateDisabled;\r
-    ReleaseSpinLock (&CpuData->CpuDataLock);\r
-  } else {\r
-    AcquireSpinLock (&CpuData->CpuDataLock);\r
-    CpuData->State = CpuStateIdle;\r
-    ReleaseSpinLock (&CpuData->CpuDataLock);\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Test memory region of EfiGcdMemoryTypeReserved.\r
-\r
-  @param  Length           The length of memory region to test.\r
-\r
-  @retval EFI_SUCCESS      The memory region passes test.\r
-  @retval EFI_NOT_FOUND    The memory region is not reserved memory.\r
-  @retval EFI_DEVICE_ERROR The memory fails on test.\r
-\r
-**/\r
-EFI_STATUS\r
-TestReservedMemory (\r
-  UINTN  Length\r
-  )\r
-{\r
-  EFI_STATUS                       Status;\r
-  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  Descriptor;\r
-  EFI_PHYSICAL_ADDRESS             Address;\r
-  UINTN                            LengthCovered;\r
-  UINTN                            RemainingLength;\r
-\r
-  //\r
-  // Walk through the memory descriptors covering the memory range.\r
-  //\r
-  Address         = mStartupVector;\r
-  RemainingLength = Length;\r
-  while (Address < mStartupVector + Length) {\r
-    Status = gDS->GetMemorySpaceDescriptor(\r
-                    Address,\r
-                    &Descriptor\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-\r
-    if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-    //\r
-    // Calculated the length of the intersected range.\r
-    //\r
-    LengthCovered = (UINTN) (Descriptor.BaseAddress + Descriptor.Length - Address);\r
-    if (LengthCovered > RemainingLength) {\r
-      LengthCovered = RemainingLength;\r
-    }\r
-\r
-    Status = mGenMemoryTest->CompatibleRangeTest (\r
-                               mGenMemoryTest,\r
-                               Address,\r
-                               LengthCovered\r
-                               );\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_DEVICE_ERROR;\r
-    }\r
-\r
-    Address         += LengthCovered;\r
-    RemainingLength -= LengthCovered;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Allocates startup vector for APs.\r
-\r
-  This function allocates Startup vector for APs.\r
-\r
-  @param  Size  The size of startup vector.\r
-\r
-**/\r
-VOID\r
-AllocateStartupVector (\r
-  UINTN   Size\r
-  )\r
-{\r
-  EFI_STATUS                            Status;\r
-\r
-  Status = gBS->LocateProtocol (\r
-                  &gEfiGenericMemTestProtocolGuid,\r
-                  NULL,\r
-                  (VOID **) &mGenMemoryTest\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    mGenMemoryTest = NULL;\r
-  }\r
-\r
-  for (mStartupVector = 0x7F000; mStartupVector >= 0x2000; mStartupVector -= EFI_PAGE_SIZE) {\r
-    if (mGenMemoryTest != NULL) {\r
-      //\r
-      // Test memory if it is EfiGcdMemoryTypeReserved.\r
-      //\r
-      Status = TestReservedMemory (EFI_SIZE_TO_PAGES (Size) * EFI_PAGE_SIZE);\r
-      if (Status == EFI_DEVICE_ERROR) {\r
-        continue;\r
-      }\r
-    }\r
-\r
-    Status = gBS->AllocatePages (\r
-                    AllocateAddress,\r
-                    EfiBootServicesCode,\r
-                    EFI_SIZE_TO_PAGES (Size),\r
-                    &mStartupVector\r
-                    );\r
-\r
-    if (!EFI_ERROR (Status)) {\r
-      break;\r
-    }\r
-  }\r
-\r
-  ASSERT_EFI_ERROR (Status);\r
-}\r
-\r
-/**\r
-  Prepares Startup Vector for APs.\r
-\r
-  This function prepares Startup Vector for APs.\r
-\r
-**/\r
-VOID\r
-PrepareAPStartupVector (\r
-  VOID\r
-  )\r
-{\r
-  MP_ASSEMBLY_ADDRESS_MAP   AddressMap;\r
-  IA32_DESCRIPTOR           GdtrForBSP;\r
-  IA32_DESCRIPTOR           IdtrForBSP;\r
-  EFI_PHYSICAL_ADDRESS      GdtForAP;\r
-  EFI_PHYSICAL_ADDRESS      IdtForAP;\r
-  EFI_STATUS                Status;\r
-\r
-  //\r
-  // Get the address map of startup code for AP,\r
-  // including code size, and offset of long jump instructions to redirect.\r
-  //\r
-  AsmGetAddressMap (&AddressMap);\r
-\r
-  //\r
-  // Allocate a 4K-aligned region under 1M for startup vector for AP.\r
-  // The region contains AP startup code and exchange data between BSP and AP.\r
-  //\r
-  AllocateStartupVector (AddressMap.Size + sizeof (MP_CPU_EXCHANGE_INFO));\r
-\r
-  //\r
-  // Copy AP startup code to startup vector, and then redirect the long jump\r
-  // instructions for mode switching.\r
-  //\r
-  CopyMem ((VOID *) (UINTN) mStartupVector, AddressMap.RendezvousFunnelAddress, AddressMap.Size);\r
-  *(UINT32 *) (UINTN) (mStartupVector + AddressMap.FlatJumpOffset + 3) = (UINT32) (mStartupVector + AddressMap.PModeEntryOffset);\r
-  //\r
-  // For IA32 mode, LongJumpOffset is filled with zero. If non-zero, then we are in X64 mode, so further redirect for long mode switch.\r
-  //\r
-  if (AddressMap.LongJumpOffset != 0) {\r
-    *(UINT32 *) (UINTN) (mStartupVector + AddressMap.LongJumpOffset + 2) = (UINT32) (mStartupVector + AddressMap.LModeEntryOffset);\r
-  }\r
-\r
-  //\r
-  // Get the start address of exchange data between BSP and AP.\r
-  //\r
-  mExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mStartupVector + AddressMap.Size);\r
-\r
-  ZeroMem ((VOID *) mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO));\r
-\r
-  mExchangeInfo->StackStart  = AllocatePages (EFI_SIZE_TO_PAGES (mNumberOfProcessors * AP_STACK_SIZE));\r
-  mExchangeInfo->StackSize  = AP_STACK_SIZE;\r
-\r
-  AsmReadGdtr (&GdtrForBSP);\r
-  AsmReadIdtr (&IdtrForBSP);\r
-\r
-  //\r
-  // Allocate memory under 4G to hold GDT for APs\r
-  //\r
-  GdtForAP = 0xffffffff;\r
-  Status   = gBS->AllocatePages (\r
-                    AllocateMaxAddress,\r
-                    EfiBootServicesData,\r
-                    EFI_SIZE_TO_PAGES ((GdtrForBSP.Limit + 1) + (IdtrForBSP.Limit + 1)),\r
-                    &GdtForAP\r
-                    );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  IdtForAP = (UINTN) GdtForAP + GdtrForBSP.Limit + 1;\r
-\r
-  CopyMem ((VOID *) (UINTN) GdtForAP, (VOID *) GdtrForBSP.Base, GdtrForBSP.Limit + 1);\r
-  CopyMem ((VOID *) (UINTN) IdtForAP, (VOID *) IdtrForBSP.Base, IdtrForBSP.Limit + 1);\r
-\r
-  mExchangeInfo->GdtrProfile.Base  = (UINTN) GdtForAP;\r
-  mExchangeInfo->GdtrProfile.Limit = GdtrForBSP.Limit;\r
-  mExchangeInfo->IdtrProfile.Base  = (UINTN) IdtForAP;\r
-  mExchangeInfo->IdtrProfile.Limit = IdtrForBSP.Limit;\r
-\r
-  mExchangeInfo->BufferStart = (UINT32) mStartupVector;\r
-  mExchangeInfo->Cr3         = (UINT32) (AsmReadCr3 ());\r
-}\r
-\r
-/**\r
-  Prepares memory region for processor configuration.\r
-\r
-  This function prepares memory region for processor configuration.\r
-\r
-**/\r
-VOID\r
-PrepareMemoryForConfiguration (\r
-  VOID\r
-  )\r
-{\r
-  UINTN                Index;\r
-\r
-  //\r
-  // Initialize Spin Locks for system\r
-  //\r
-  InitializeSpinLock (&mMPSystemData.APSerializeLock);\r
-  for (Index = 0; Index < MAX_CPU_NUMBER; Index++) {\r
-    InitializeSpinLock (&mMPSystemData.CpuData[Index].CpuDataLock);\r
-  }\r
-\r
-  PrepareAPStartupVector ();\r
-}\r
-\r
-/**\r
-  Gets the processor number of BSP.\r
-\r
-  @return  The processor number of BSP.\r
-\r
-**/\r
-UINTN\r
-GetBspNumber (\r
-  VOID\r
-  )\r
-{\r
-  UINTN                      ProcessorNumber;\r
-  EFI_MP_PROC_CONTEXT        ProcessorContextBuffer;\r
-  EFI_STATUS                 Status;\r
-  UINTN                      BufferSize;\r
-\r
-  BufferSize = sizeof (EFI_MP_PROC_CONTEXT);\r
-\r
-  for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {\r
-    Status = mFrameworkMpService->GetProcessorContext (\r
-                                    mFrameworkMpService,\r
-                                    ProcessorNumber,\r
-                                    &BufferSize,\r
-                                    &ProcessorContextBuffer\r
-                                    );\r
-    ASSERT_EFI_ERROR (Status);\r
-\r
-    if (ProcessorContextBuffer.Designation == EfiCpuBSP) {\r
-      break;\r
-    }\r
-  }\r
-  ASSERT (ProcessorNumber < mNumberOfProcessors);\r
-\r
-  return ProcessorNumber;\r
-}\r
-\r
-/**\r
-  Entrypoint of MP Services Protocol thunk driver.\r
-\r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
-  @param[in] SystemTable    A pointer to the EFI System Table.\r
-\r
-  @retval EFI_SUCCESS       The entry point is executed successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InitializeMpServicesProtocol (\r
-  IN EFI_HANDLE        ImageHandle,\r
-  IN EFI_SYSTEM_TABLE  *SystemTable\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-\r
-  //\r
-  // Locates Framework version MP Services Protocol\r
-  //\r
-  Status = gBS->LocateProtocol (\r
-                  &gFrameworkEfiMpServiceProtocolGuid,\r
-                  NULL,\r
-                  (VOID **) &mFrameworkMpService\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = mFrameworkMpService->GetGeneralMPInfo (\r
-                                  mFrameworkMpService,\r
-                                  &mNumberOfProcessors,\r
-                                  NULL,\r
-                                  NULL,\r
-                                  NULL,\r
-                                  NULL\r
-                                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-  ASSERT (mNumberOfProcessors < MAX_CPU_NUMBER);\r
-\r
-  PrepareMemoryForConfiguration ();\r
-\r
-  //\r
-  // Create timer event to check AP state for non-blocking execution.\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  CheckAPsStatus,\r
-                  NULL,\r
-                  &mMPSystemData.CheckAPsEvent\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Now install the MP services protocol.\r
-  //\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &mHandle,\r
-                  &gEfiMpServiceProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &mMpService\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Launch the timer event to check AP state.\r
-  //\r
-  Status = gBS->SetTimer (\r
-                  mMPSystemData.CheckAPsEvent,\r
-                  TimerPeriodic,\r
-                  100000\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  return EFI_SUCCESS;\r
-}\r