MdeModulePkg PeiCore: Recheck SwitchStackSignal after ProcessNotifyList()

in case PeiInstallPeiMemory() is done in a callback with
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, and the callback is registered on
a PPI that is installed in the last PEIM.

At the case, PeiCore SwitchStack code will be not being invoked.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18305 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Star Zeng 2015-08-25 07:05:48 +00:00 committed by lzeng14
parent a60a462e53
commit bfb685da6f
1 changed files with 293 additions and 263 deletions

View File

@ -627,52 +627,39 @@ PeiCoreEntry (
} }
/** /**
Conduct PEIM dispatch. Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.
@param SecCoreData Points to a data structure containing information about the PEI core's operating @param[in] SecCoreData Points to a data structure containing information about the PEI core's operating
environment, such as the size and location of temporary RAM, the stack location and environment, such as the size and location of temporary RAM, the stack location and
the BFV location. the BFV location.
@param Private Pointer to the private data passed in from caller @param[in] Private Pointer to the private data passed in from caller.
**/ **/
VOID VOID
PeiDispatcher ( PeiCheckAndSwitchStack (
IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
IN PEI_CORE_INSTANCE *Private IN PEI_CORE_INSTANCE *Private
) )
{ {
VOID *LoadFixPeiCodeBegin;
EFI_STATUS Status; EFI_STATUS Status;
UINT32 Index1;
UINT32 Index2;
CONST EFI_PEI_SERVICES **PeiServices; CONST EFI_PEI_SERVICES **PeiServices;
EFI_PEI_FILE_HANDLE PeimFileHandle;
UINTN FvCount;
UINTN PeimCount;
UINT32 AuthenticationState;
EFI_PHYSICAL_ADDRESS EntryPoint;
EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;
UINTN SaveCurrentPeimCount;
UINTN SaveCurrentFvCount;
EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
UINT64 NewStackSize; UINT64 NewStackSize;
UINTN HeapTemporaryRamSize;
EFI_PHYSICAL_ADDRESS BaseOfNewHeap;
EFI_PHYSICAL_ADDRESS TopOfNewStack;
EFI_PHYSICAL_ADDRESS TopOfOldStack; EFI_PHYSICAL_ADDRESS TopOfOldStack;
EFI_PHYSICAL_ADDRESS TopOfNewStack;
UINTN StackOffset;
BOOLEAN StackOffsetPositive;
EFI_PHYSICAL_ADDRESS TemporaryRamBase; EFI_PHYSICAL_ADDRESS TemporaryRamBase;
UINTN TemporaryRamSize; UINTN TemporaryRamSize;
UINTN TemporaryStackSize; UINTN TemporaryStackSize;
VOID *TemporaryStackBase; VOID *TemporaryStackBase;
UINTN PeiTemporaryRamSize; UINTN PeiTemporaryRamSize;
VOID *PeiTemporaryRamBase; VOID *PeiTemporaryRamBase;
UINTN StackOffset; EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
BOOLEAN StackOffsetPositive; EFI_PHYSICAL_ADDRESS BaseOfNewHeap;
EFI_PHYSICAL_ADDRESS HoleMemBase; EFI_PHYSICAL_ADDRESS HoleMemBase;
UINTN HoleMemSize; UINTN HoleMemSize;
EFI_FV_FILE_INFO FvFileInfo; UINTN HeapTemporaryRamSize;
PEI_CORE_FV_HANDLE *CoreFvHandle;
VOID *LoadFixPeiCodeBegin;
EFI_PHYSICAL_ADDRESS TempBase1; EFI_PHYSICAL_ADDRESS TempBase1;
UINTN TempSize1; UINTN TempSize1;
EFI_PHYSICAL_ADDRESS TempBase2; EFI_PHYSICAL_ADDRESS TempBase2;
@ -680,178 +667,6 @@ PeiDispatcher (
UINTN Index; UINTN Index;
PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps; PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;
PeimEntryPoint = NULL;
PeimFileHandle = NULL;
EntryPoint = 0;
if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {
//
// Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
// update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
//
SaveCurrentPeimCount = Private->CurrentPeimCount;
SaveCurrentFvCount = Private->CurrentPeimFvCount;
SaveCurrentFileHandle = Private->CurrentFileHandle;
for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {
for (Index2 = 0; (Index2 < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {
if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {
PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
Private->CurrentFileHandle = PeimFileHandle;
Private->CurrentPeimFvCount = Index1;
Private->CurrentPeimCount = Index2;
Status = PeiLoadImage (
(CONST EFI_PEI_SERVICES **) &Private->Ps,
PeimFileHandle,
PEIM_STATE_REGISITER_FOR_SHADOW,
&EntryPoint,
&AuthenticationState
);
if (Status == EFI_SUCCESS) {
//
// PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
//
Private->Fv[Index1].PeimState[Index2]++;
//
// Call the PEIM entry point
//
PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
PERF_START (PeimFileHandle, "PEIM", NULL, 0);
PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);
PERF_END (PeimFileHandle, "PEIM", NULL, 0);
}
//
// Process the Notify list and dispatch any notifies for
// newly installed PPIs.
//
ProcessNotifyList (Private);
}
}
}
Private->CurrentFileHandle = SaveCurrentFileHandle;
Private->CurrentPeimFvCount = SaveCurrentFvCount;
Private->CurrentPeimCount = SaveCurrentPeimCount;
}
//
// This is the main dispatch loop. It will search known FVs for PEIMs and
// attempt to dispatch them. If any PEIM gets dispatched through a single
// pass of the dispatcher, it will start over from the Bfv again to see
// if any new PEIMs dependencies got satisfied. With a well ordered
// FV where PEIMs are found in the order their dependencies are also
// satisfied, this dipatcher should run only once.
//
do {
//
// In case that reenter PeiCore happens, the last pass record is still available.
//
if (!Private->PeimDispatcherReenter) {
Private->PeimNeedingDispatch = FALSE;
Private->PeimDispatchOnThisPass = FALSE;
} else {
Private->PeimDispatcherReenter = FALSE;
}
for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);
ASSERT (CoreFvHandle != NULL);
//
// If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
//
if (CoreFvHandle->FvPpi == NULL) {
continue;
}
Private->CurrentPeimFvCount = FvCount;
if (Private->CurrentPeimCount == 0) {
//
// When going through each FV, at first, search Apriori file to
// reorder all PEIMs to ensure the PEIMs in Apriori file to get
// dispatch at first.
//
DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);
}
//
// Start to dispatch all modules within the current Fv.
//
for (PeimCount = Private->CurrentPeimCount;
(PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
PeimCount++) {
Private->CurrentPeimCount = PeimCount;
PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
Private->PeimNeedingDispatch = TRUE;
} else {
Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);
ASSERT_EFI_ERROR (Status);
if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
//
// For Fv type file, Produce new FV PPI and FV hob
//
Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle);
if (Status == EFI_SUCCESS) {
//
// PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
//
Private->Fv[FvCount].PeimState[PeimCount]++;
Private->PeimDispatchOnThisPass = TRUE;
}
} else {
//
// For PEIM driver, Load its entry point
//
Status = PeiLoadImage (
PeiServices,
PeimFileHandle,
PEIM_STATE_NOT_DISPATCHED,
&EntryPoint,
&AuthenticationState
);
if (Status == EFI_SUCCESS) {
//
// The PEIM has its dependencies satisfied, and its entry point
// has been found, so invoke it.
//
PERF_START (PeimFileHandle, "PEIM", NULL, 0);
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
EFI_PROGRESS_CODE,
(EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
(VOID *)(&PeimFileHandle),
sizeof (PeimFileHandle)
);
Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState);
if (Status != EFI_SECURITY_VIOLATION) {
//
// PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
//
Private->Fv[FvCount].PeimState[PeimCount]++;
//
// Call the PEIM entry point for PEIM driver
//
PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
Private->PeimDispatchOnThisPass = TRUE;
}
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
EFI_PROGRESS_CODE,
(EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),
(VOID *)(&PeimFileHandle),
sizeof (PeimFileHandle)
);
PERF_END (PeimFileHandle, "PEIM", NULL, 0);
}
}
if (Private->SwitchStackSignal) { if (Private->SwitchStackSignal) {
// //
@ -1094,12 +909,227 @@ PeiDispatcher (
// //
ASSERT (FALSE); ASSERT (FALSE);
} }
}
/**
Conduct PEIM dispatch.
@param SecCoreData Points to a data structure containing information about the PEI core's operating
environment, such as the size and location of temporary RAM, the stack location and
the BFV location.
@param Private Pointer to the private data passed in from caller
**/
VOID
PeiDispatcher (
IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
IN PEI_CORE_INSTANCE *Private
)
{
EFI_STATUS Status;
UINT32 Index1;
UINT32 Index2;
CONST EFI_PEI_SERVICES **PeiServices;
EFI_PEI_FILE_HANDLE PeimFileHandle;
UINTN FvCount;
UINTN PeimCount;
UINT32 AuthenticationState;
EFI_PHYSICAL_ADDRESS EntryPoint;
EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;
UINTN SaveCurrentPeimCount;
UINTN SaveCurrentFvCount;
EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
EFI_FV_FILE_INFO FvFileInfo;
PEI_CORE_FV_HANDLE *CoreFvHandle;
PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;
PeimEntryPoint = NULL;
PeimFileHandle = NULL;
EntryPoint = 0;
if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {
//
// Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
// update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.
//
SaveCurrentPeimCount = Private->CurrentPeimCount;
SaveCurrentFvCount = Private->CurrentPeimFvCount;
SaveCurrentFileHandle = Private->CurrentFileHandle;
for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {
for (Index2 = 0; (Index2 < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {
if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {
PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
Private->CurrentFileHandle = PeimFileHandle;
Private->CurrentPeimFvCount = Index1;
Private->CurrentPeimCount = Index2;
Status = PeiLoadImage (
(CONST EFI_PEI_SERVICES **) &Private->Ps,
PeimFileHandle,
PEIM_STATE_REGISITER_FOR_SHADOW,
&EntryPoint,
&AuthenticationState
);
if (Status == EFI_SUCCESS) {
//
// PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
//
Private->Fv[Index1].PeimState[Index2]++;
//
// Call the PEIM entry point
//
PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
PERF_START (PeimFileHandle, "PEIM", NULL, 0);
PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->Ps);
PERF_END (PeimFileHandle, "PEIM", NULL, 0);
}
// //
// Process the Notify list and dispatch any notifies for // Process the Notify list and dispatch any notifies for
// newly installed PPIs. // newly installed PPIs.
// //
ProcessNotifyList (Private); ProcessNotifyList (Private);
}
}
}
Private->CurrentFileHandle = SaveCurrentFileHandle;
Private->CurrentPeimFvCount = SaveCurrentFvCount;
Private->CurrentPeimCount = SaveCurrentPeimCount;
}
//
// This is the main dispatch loop. It will search known FVs for PEIMs and
// attempt to dispatch them. If any PEIM gets dispatched through a single
// pass of the dispatcher, it will start over from the Bfv again to see
// if any new PEIMs dependencies got satisfied. With a well ordered
// FV where PEIMs are found in the order their dependencies are also
// satisfied, this dipatcher should run only once.
//
do {
//
// In case that reenter PeiCore happens, the last pass record is still available.
//
if (!Private->PeimDispatcherReenter) {
Private->PeimNeedingDispatch = FALSE;
Private->PeimDispatchOnThisPass = FALSE;
} else {
Private->PeimDispatcherReenter = FALSE;
}
for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
CoreFvHandle = FindNextCoreFvHandle (Private, FvCount);
ASSERT (CoreFvHandle != NULL);
//
// If the FV has corresponding EFI_PEI_FIRMWARE_VOLUME_PPI instance, then dispatch it.
//
if (CoreFvHandle->FvPpi == NULL) {
continue;
}
Private->CurrentPeimFvCount = FvCount;
if (Private->CurrentPeimCount == 0) {
//
// When going through each FV, at first, search Apriori file to
// reorder all PEIMs to ensure the PEIMs in Apriori file to get
// dispatch at first.
//
DiscoverPeimsAndOrderWithApriori (Private, CoreFvHandle);
}
//
// Start to dispatch all modules within the current Fv.
//
for (PeimCount = Private->CurrentPeimCount;
(PeimCount < PcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
PeimCount++) {
Private->CurrentPeimCount = PeimCount;
PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
Private->PeimNeedingDispatch = TRUE;
} else {
Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeimFileHandle, &FvFileInfo);
ASSERT_EFI_ERROR (Status);
if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
//
// For Fv type file, Produce new FV PPI and FV hob
//
Status = ProcessFvFile (Private, &Private->Fv[FvCount], PeimFileHandle);
if (Status == EFI_SUCCESS) {
//
// PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
//
Private->Fv[FvCount].PeimState[PeimCount]++;
Private->PeimDispatchOnThisPass = TRUE;
}
} else {
//
// For PEIM driver, Load its entry point
//
Status = PeiLoadImage (
PeiServices,
PeimFileHandle,
PEIM_STATE_NOT_DISPATCHED,
&EntryPoint,
&AuthenticationState
);
if (Status == EFI_SUCCESS) {
//
// The PEIM has its dependencies satisfied, and its entry point
// has been found, so invoke it.
//
PERF_START (PeimFileHandle, "PEIM", NULL, 0);
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
EFI_PROGRESS_CODE,
(EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
(VOID *)(&PeimFileHandle),
sizeof (PeimFileHandle)
);
Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle, AuthenticationState);
if (Status != EFI_SECURITY_VIOLATION) {
//
// PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
//
Private->Fv[FvCount].PeimState[PeimCount]++;
//
// Call the PEIM entry point for PEIM driver
//
PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
Private->PeimDispatchOnThisPass = TRUE;
}
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
EFI_PROGRESS_CODE,
(EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END),
(VOID *)(&PeimFileHandle),
sizeof (PeimFileHandle)
);
PERF_END (PeimFileHandle, "PEIM", NULL, 0);
}
}
PeiCheckAndSwitchStack (SecCoreData, Private);
//
// Process the Notify list and dispatch any notifies for
// newly installed PPIs.
//
ProcessNotifyList (Private);
//
// Recheck SwitchStackSignal after ProcessNotifyList()
// in case PeiInstallPeiMemory() is done in a callback with
// EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH.
//
PeiCheckAndSwitchStack (SecCoreData, Private);
if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \ if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \
(Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) { (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {