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
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
PeiDispatcher (
PeiCheckAndSwitchStack (
IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
IN PEI_CORE_INSTANCE *Private
)
{
VOID *LoadFixPeiCodeBegin;
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_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
UINT64 NewStackSize;
UINTN HeapTemporaryRamSize;
EFI_PHYSICAL_ADDRESS BaseOfNewHeap;
EFI_PHYSICAL_ADDRESS TopOfNewStack;
EFI_PHYSICAL_ADDRESS TopOfOldStack;
EFI_PHYSICAL_ADDRESS TopOfNewStack;
UINTN StackOffset;
BOOLEAN StackOffsetPositive;
EFI_PHYSICAL_ADDRESS TemporaryRamBase;
UINTN TemporaryRamSize;
UINTN TemporaryStackSize;
VOID *TemporaryStackBase;
UINTN PeiTemporaryRamSize;
VOID *PeiTemporaryRamBase;
UINTN StackOffset;
BOOLEAN StackOffsetPositive;
EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
EFI_PHYSICAL_ADDRESS BaseOfNewHeap;
EFI_PHYSICAL_ADDRESS HoleMemBase;
UINTN HoleMemSize;
EFI_FV_FILE_INFO FvFileInfo;
PEI_CORE_FV_HANDLE *CoreFvHandle;
VOID *LoadFixPeiCodeBegin;
UINTN HeapTemporaryRamSize;
EFI_PHYSICAL_ADDRESS TempBase1;
UINTN TempSize1;
EFI_PHYSICAL_ADDRESS TempBase2;
@ -680,178 +667,6 @@ PeiDispatcher (
UINTN Index;
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) {
//
@ -1094,12 +909,227 @@ PeiDispatcher (
//
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
// 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);
}
}
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) && \
(Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {