- PEI_CPU_MP_DATA *PeiCpuMpData;\r
- UINTN ProcessorNumber;\r
- UINTN Index;\r
- UINTN CallerNumber;\r
- BOOLEAN HasEnabledAp;\r
- BOOLEAN HasEnabledIdleAp;\r
- volatile UINT32 *FinishedCount;\r
- EFI_STATUS Status;\r
- UINTN WaitCountIndex;\r
- UINTN WaitCountNumber;\r
-\r
- PeiCpuMpData = GetMpHobData ();\r
- if (PeiCpuMpData == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- if (Procedure == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Check whether caller processor is BSP\r
- //\r
- PeiWhoAmI (PeiServices, This, &CallerNumber);\r
- if (CallerNumber != PeiCpuMpData->BspNumber) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- ProcessorNumber = PeiCpuMpData->CpuCount;\r
-\r
- HasEnabledAp = FALSE;\r
- HasEnabledIdleAp = FALSE;\r
- for (Index = 0; Index < ProcessorNumber; Index ++) {\r
- if (Index == CallerNumber) {\r
- //\r
- // Skip BSP\r
- //\r
- continue;\r
- }\r
- if (PeiCpuMpData->CpuData[Index].State != CpuStateDisabled) {\r
- HasEnabledAp = TRUE;\r
- if (PeiCpuMpData->CpuData[Index].State != CpuStateBusy) {\r
- HasEnabledIdleAp = TRUE;\r
- }\r
- }\r
- }\r
- if (!HasEnabledAp) {\r
- //\r
- // If no enabled AP exists, return EFI_NOT_STARTED.\r
- //\r
- return EFI_NOT_STARTED;\r
- }\r
- if (!HasEnabledIdleAp) {\r
- //\r
- // If any enabled APs are busy, return EFI_NOT_READY.\r
- //\r
- return EFI_NOT_READY;\r
- }\r
-\r
- if (PeiCpuMpData->EndOfPeiFlag) {\r
- //\r
- // Backup original data and copy AP reset vector in it\r
- //\r
- BackupAndPrepareWakeupBuffer(PeiCpuMpData);\r
- }\r
-\r
- WaitCountNumber = TimeoutInMicroSeconds / CPU_CHECK_AP_INTERVAL + 1;\r
- WaitCountIndex = 0;\r
- FinishedCount = &PeiCpuMpData->FinishedCount;\r
- if (!SingleThread) {\r
- WakeUpAP (PeiCpuMpData, TRUE, 0, Procedure, ProcedureArgument);\r
- //\r
- // Wait to finish\r
- //\r
- if (TimeoutInMicroSeconds == 0) {\r
- while (*FinishedCount < ProcessorNumber - 1) {\r
- CpuPause ();\r
- }\r
- Status = EFI_SUCCESS;\r
- } else {\r
- Status = EFI_TIMEOUT;\r
- for (WaitCountIndex = 0; WaitCountIndex < WaitCountNumber; WaitCountIndex++) {\r
- MicroSecondDelay (CPU_CHECK_AP_INTERVAL);\r
- if (*FinishedCount >= ProcessorNumber - 1) {\r
- Status = EFI_SUCCESS;\r
- break;\r
- }\r
- }\r
- }\r
- } else {\r
- Status = EFI_SUCCESS;\r
- for (Index = 0; Index < ProcessorNumber; Index++) {\r
- if (Index == CallerNumber) {\r
- continue;\r
- }\r
- WakeUpAP (PeiCpuMpData, FALSE, Index, Procedure, ProcedureArgument);\r
- //\r
- // Wait to finish\r
- //\r
- if (TimeoutInMicroSeconds == 0) {\r
- while (*FinishedCount < 1) {\r
- CpuPause ();\r
- }\r
- } else {\r
- for (WaitCountIndex = 0; WaitCountIndex < WaitCountNumber; WaitCountIndex++) {\r
- MicroSecondDelay (CPU_CHECK_AP_INTERVAL);\r
- if (*FinishedCount >= 1) {\r
- break;\r
- }\r
- }\r
- if (WaitCountIndex == WaitCountNumber) {\r
- Status = EFI_TIMEOUT;\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (PeiCpuMpData->EndOfPeiFlag) {\r
- //\r
- // Restore original data\r
- //\r
- RestoreWakeupBuffer(PeiCpuMpData);\r
- }\r
-\r
- return Status;\r