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