Merge branch of PI tree to main trunk
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3918 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -23,12 +23,6 @@ Revision History
|
||||
|
||||
#include <PeiMain.h>
|
||||
|
||||
STATIC
|
||||
VOID *
|
||||
TransferOldDataToNewDataRange (
|
||||
IN PEI_CORE_INSTANCE *PrivateData
|
||||
);
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
InvokePeiCore (
|
||||
@@ -36,11 +30,165 @@ InvokePeiCore (
|
||||
VOID *Context2
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
|
||||
VOID
|
||||
DiscoverPeimsAndOrderWithApriori (
|
||||
IN PEI_CORE_INSTANCE *Private,
|
||||
IN EFI_PEI_FV_HANDLE VolumeHandle
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Discover all Peims and optional Apriori file in one FV. There is at most one
|
||||
Apriori file in one FV.
|
||||
|
||||
Arguments:
|
||||
|
||||
Private - Pointer to the private data passed in from caller
|
||||
VolumeHandle - Fv handle.
|
||||
Returns:
|
||||
|
||||
NONE
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_PEI_FV_HANDLE FileHandle;
|
||||
EFI_PEI_FV_HANDLE AprioriFileHandle;
|
||||
EFI_GUID *Apriori;
|
||||
UINTN Index;
|
||||
UINTN Index2;
|
||||
UINTN PeimIndex;
|
||||
UINTN PeimCount;
|
||||
EFI_GUID *Guid;
|
||||
EFI_PEI_FV_HANDLE TempFileHandles[PEI_CORE_MAX_PEIM_PER_FV];
|
||||
EFI_GUID FileGuid[PEI_CORE_MAX_PEIM_PER_FV];
|
||||
|
||||
//
|
||||
// Walk the FV and find all the PEIMs and the Apriori file.
|
||||
//
|
||||
AprioriFileHandle = NULL;
|
||||
Private->CurrentFvFileHandles[0] = NULL;
|
||||
Guid = NULL;
|
||||
FileHandle = NULL;
|
||||
|
||||
//
|
||||
// If the current Fv has been scanned, directly get its cachable record.
|
||||
//
|
||||
if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {
|
||||
CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Go ahead to scan this Fv, and cache FileHandles within it.
|
||||
//
|
||||
for (PeimCount = 0; PeimCount < PEI_CORE_MAX_PEIM_PER_FV; PeimCount++) {
|
||||
Status = PeiFindFileEx (
|
||||
VolumeHandle,
|
||||
NULL,
|
||||
PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
|
||||
&FileHandle,
|
||||
&AprioriFileHandle
|
||||
);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
Private->CurrentFvFileHandles[PeimCount] = FileHandle;
|
||||
}
|
||||
|
||||
Private->AprioriCount = 0;
|
||||
if (AprioriFileHandle != NULL) {
|
||||
//
|
||||
// Read the Apriori file
|
||||
//
|
||||
Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, &AprioriFileHandle, (VOID **) &Apriori);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Calculate the number of PEIMs in the A Priori list
|
||||
//
|
||||
Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF;
|
||||
Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER);
|
||||
Private->AprioriCount /= sizeof (EFI_GUID);
|
||||
|
||||
SetMem (FileGuid, sizeof (FileGuid), 0);
|
||||
for (Index = 0; Index < PeimCount; Index++) {
|
||||
//
|
||||
// Make an array of file name guids that matches the FileHandle array so we can convert
|
||||
// quickly from file name to file handle
|
||||
//
|
||||
CopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID));
|
||||
}
|
||||
|
||||
//
|
||||
// Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.
|
||||
// Add avalible PEIMs in Apriori file into TempFileHandles array at first.
|
||||
//
|
||||
Index2 = 0;
|
||||
for (Index = 0; Index2 < Private->AprioriCount; Index++) {
|
||||
while (Index2 < Private->AprioriCount) {
|
||||
Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);
|
||||
if (Guid != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Guid == NULL) {
|
||||
break;
|
||||
}
|
||||
PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);
|
||||
TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];
|
||||
|
||||
//
|
||||
// Since we have copied the file handle we can remove it from this list.
|
||||
//
|
||||
Private->CurrentFvFileHandles[PeimIndex] = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Update valid Aprioricount
|
||||
//
|
||||
Private->AprioriCount = Index;
|
||||
|
||||
//
|
||||
// Add in any PEIMs not in the Apriori file
|
||||
//
|
||||
for (;Index < PeimCount; Index++) {
|
||||
for (Index2 = 0; Index2 < PeimCount; Index2++) {
|
||||
if (Private->CurrentFvFileHandles[Index2] != NULL) {
|
||||
TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];
|
||||
Private->CurrentFvFileHandles[Index2] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//Index the end of array contains re-range Pei moudle.
|
||||
//
|
||||
TempFileHandles[Index] = NULL;
|
||||
|
||||
//
|
||||
// Private->CurrentFvFileHandles is currently in PEIM in the FV order.
|
||||
// We need to update it to start with files in the A Priori list and
|
||||
// then the remaining files in PEIM order.
|
||||
//
|
||||
CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles));
|
||||
}
|
||||
}
|
||||
//
|
||||
// Cache the current Fv File Handle. So that we don't have to scan the Fv again.
|
||||
// Instead, we can retrieve the file handles within this Fv from cachable data.
|
||||
//
|
||||
Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;
|
||||
CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
PeiDispatcher (
|
||||
IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
|
||||
IN PEI_CORE_INSTANCE *PrivateData,
|
||||
IN PEI_CORE_DISPATCH_DATA *DispatchData
|
||||
IN PEI_CORE_INSTANCE *Private
|
||||
)
|
||||
|
||||
/*++
|
||||
@@ -64,24 +212,78 @@ Returns:
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
PEI_CORE_TEMP_POINTERS TempPtr;
|
||||
BOOLEAN NextFvFound;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *NextFvAddress;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *DefaultFvAddress;
|
||||
VOID *TopOfStack;
|
||||
PEI_CORE_PARAMETERS PeiCoreParameters;
|
||||
EFI_STATUS Status;
|
||||
UINT32 Index1;
|
||||
UINT32 Index2;
|
||||
EFI_PEI_SERVICES **PeiServices;
|
||||
VOID *PrivateInMem;
|
||||
EFI_PEI_FV_HANDLE VolumeHandle;
|
||||
EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
|
||||
EFI_PEI_FILE_HANDLE PeimFileHandle;
|
||||
UINTN FvCount;
|
||||
UINTN PeimCount;
|
||||
UINT32 AuthenticationState;
|
||||
EFI_PHYSICAL_ADDRESS EntryPoint;
|
||||
EFI_PEIM_ENTRY_POINT PeimEntryPoint;
|
||||
BOOLEAN PeimNeedingDispatch;
|
||||
BOOLEAN PeimDispatchOnThisPass;
|
||||
UINTN SaveCurrentPeimCount;
|
||||
EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
|
||||
VOID *TopOfStack;
|
||||
PEI_CORE_PARAMETERS PeiCoreParameters;
|
||||
EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
|
||||
|
||||
//
|
||||
// Debug data for uninstalled Peim list
|
||||
//
|
||||
EFI_GUID DebugFoundPeimList[32];
|
||||
EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
|
||||
|
||||
//
|
||||
// save the Current FV Address so that we will not process it again if FindFv returns it later
|
||||
//
|
||||
DefaultFvAddress = DispatchData->BootFvAddress;
|
||||
PeiServices = &Private->PS;
|
||||
PeimEntryPoint = NULL;
|
||||
PeimFileHandle = NULL;
|
||||
|
||||
if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
|
||||
//
|
||||
// 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;
|
||||
SaveCurrentFileHandle = Private->CurrentFileHandle;
|
||||
|
||||
for (Index1 = 0;Index1 <= Private->CurrentPeimFvCount; Index1++) {
|
||||
for (Index2 = 0; (Index2 < PEI_CORE_MAX_PEIM_PER_FV) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {
|
||||
if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {
|
||||
PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];
|
||||
Status = PeiLoadImage (
|
||||
&Private->PS,
|
||||
PeimFileHandle,
|
||||
&EntryPoint,
|
||||
&AuthenticationState
|
||||
);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
//
|
||||
// PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
|
||||
//
|
||||
Private->Fv[Index1].PeimState[Index2]++;
|
||||
Private->CurrentFileHandle = PeimFileHandle;
|
||||
Private->CurrentPeimCount = Index2;
|
||||
//
|
||||
// Call the PEIM entry point
|
||||
//
|
||||
PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;
|
||||
|
||||
PERF_START (0, "PEIM", NULL, 0);
|
||||
PeimEntryPoint(PeimFileHandle, &Private->PS);
|
||||
PERF_END (0, "PEIM", NULL, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Process the Notify list and dispatch any notifies for
|
||||
// newly installed PPIs.
|
||||
//
|
||||
ProcessNotifyList (Private);
|
||||
}
|
||||
}
|
||||
}
|
||||
Private->CurrentFileHandle = SaveCurrentFileHandle;
|
||||
Private->CurrentPeimCount = SaveCurrentPeimCount;
|
||||
}
|
||||
|
||||
//
|
||||
// This is the main dispatch loop. It will search known FVs for PEIMs and
|
||||
@@ -91,69 +293,50 @@ Returns:
|
||||
// FV where PEIMs are found in the order their dependencies are also
|
||||
// satisfied, this dipatcher should run only once.
|
||||
//
|
||||
for (;;) {
|
||||
//
|
||||
// This is the PEIM search loop. It will scan through all PEIMs it can find
|
||||
// looking for PEIMs to dispatch, and will dipatch them if they have not
|
||||
// already been dispatched and all of their dependencies are met.
|
||||
// If no more PEIMs can be found in this pass through all known FVs,
|
||||
// then it will break out of this loop.
|
||||
//
|
||||
for (;;) {
|
||||
do {
|
||||
PeimNeedingDispatch = FALSE;
|
||||
PeimDispatchOnThisPass = FALSE;
|
||||
|
||||
Status = FindNextPeim (
|
||||
&PrivateData->PS,
|
||||
DispatchData->CurrentFvAddress,
|
||||
&DispatchData->CurrentPeimAddress
|
||||
);
|
||||
for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {
|
||||
Private->CurrentPeimFvCount = FvCount;
|
||||
VolumeHandle = Private->Fv[FvCount].FvHeader;
|
||||
|
||||
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, VolumeHandle);
|
||||
}
|
||||
|
||||
//
|
||||
// If we found a PEIM, check if it is dispatched. If so, go to the
|
||||
// next PEIM. If not, dispatch it if its dependencies are satisfied.
|
||||
// If its dependencies are not satisfied, go to the next PEIM.
|
||||
// Start to dispatch all modules within the current Fv.
|
||||
//
|
||||
if (Status == EFI_SUCCESS) {
|
||||
for (PeimCount = Private->CurrentPeimCount;
|
||||
(PeimCount < PEI_CORE_MAX_PEIM_PER_FV) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
|
||||
PeimCount++) {
|
||||
Private->CurrentPeimCount = PeimCount;
|
||||
PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
|
||||
//
|
||||
// Fill list of found Peims for later list of those not installed
|
||||
//
|
||||
CopyMem (
|
||||
&DebugFoundPeimList[DispatchData->CurrentPeim],
|
||||
&DispatchData->CurrentPeimAddress->Name,
|
||||
sizeof (EFI_GUID)
|
||||
);
|
||||
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
if (!Dispatched (
|
||||
DispatchData->CurrentPeim,
|
||||
DispatchData->DispatchedPeimBitMap
|
||||
)) {
|
||||
if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) {
|
||||
if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {
|
||||
if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {
|
||||
PeimNeedingDispatch = TRUE;
|
||||
} else {
|
||||
Status = PeiLoadImage (
|
||||
&PrivateData->PS,
|
||||
DispatchData->CurrentPeimAddress,
|
||||
&TempPtr.Raw
|
||||
PeiServices,
|
||||
PeimFileHandle,
|
||||
&EntryPoint,
|
||||
&AuthenticationState
|
||||
);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
|
||||
if ((Status == EFI_SUCCESS)) {
|
||||
//
|
||||
// The PEIM has its dependencies satisfied, and its entry point
|
||||
// has been found, so invoke it.
|
||||
//
|
||||
PERF_START (
|
||||
(VOID *) (UINTN) (DispatchData->CurrentPeimAddress),
|
||||
"PEIM",
|
||||
NULL,
|
||||
0
|
||||
);
|
||||
PERF_START (0, "PEIM", NULL, 0);
|
||||
|
||||
//
|
||||
// BUGBUG: Used to be EFI_PEI_REPORT_STATUS_CODE_CODE
|
||||
//
|
||||
ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress;
|
||||
ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;
|
||||
|
||||
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
|
||||
EFI_PROGRESS_CODE,
|
||||
@@ -162,24 +345,19 @@ Returns:
|
||||
sizeof (ExtendedData)
|
||||
);
|
||||
|
||||
//
|
||||
// Is this a authentic image
|
||||
//
|
||||
Status = VerifyPeim (
|
||||
&PrivateData->PS,
|
||||
DispatchData->CurrentPeimAddress
|
||||
);
|
||||
|
||||
if (Status != EFI_SECURITY_VIOLATION) {
|
||||
Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle);
|
||||
if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {
|
||||
//
|
||||
// PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
|
||||
//
|
||||
Private->Fv[FvCount].PeimState[PeimCount]++;
|
||||
|
||||
//
|
||||
// BUGBUG: Before enable PI, we need cast EFI_FFS_FILE_HEADER* to EFI_PEI_FILE_HANDLE*
|
||||
// Because we use new MdePkg's definition, but they are binary compatible in fact.
|
||||
// Call the PEIM entry point
|
||||
//
|
||||
Status = TempPtr.PeimEntry (
|
||||
(EFI_PEI_FILE_HANDLE*)DispatchData->CurrentPeimAddress,
|
||||
&PrivateData->PS
|
||||
);
|
||||
PeimEntryPoint = (EFI_PEIM_ENTRY_POINT)(UINTN)EntryPoint;
|
||||
PeimEntryPoint (PeimFileHandle, PeiServices);
|
||||
PeimDispatchOnThisPass = TRUE;
|
||||
}
|
||||
|
||||
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
|
||||
@@ -188,189 +366,146 @@ Returns:
|
||||
(VOID *)(&ExtendedData),
|
||||
sizeof (ExtendedData)
|
||||
);
|
||||
PERF_END (0, "PEIM", NULL, 0);
|
||||
|
||||
PERF_END ((VOID *) (UINTN) (DispatchData->CurrentPeimAddress), "PEIM", NULL, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Process the Notify list and dispatch any notifies for
|
||||
// newly installed PPIs.
|
||||
//
|
||||
ProcessNotifyList (Private);
|
||||
|
||||
//
|
||||
// If permanent memory was discovered and installed by this
|
||||
// PEIM, shadow PEI Core and switch the stacks to the new memory.
|
||||
//
|
||||
if (Private->SwitchStackSignal) {
|
||||
|
||||
//
|
||||
// Mark the PEIM as dispatched so we don't attempt to run it again
|
||||
// Make sure we don't retry the same PEIM that added memory
|
||||
//
|
||||
SetDispatched (
|
||||
&PrivateData->PS,
|
||||
DispatchData->CurrentPeim,
|
||||
&DispatchData->DispatchedPeimBitMap
|
||||
Private->CurrentPeimCount++;
|
||||
|
||||
//
|
||||
// Migrate IDT from CAR into real memory, so after stack switches to
|
||||
// the new memory, the caller can get memory version PeiServiceTable.
|
||||
//
|
||||
//MigrateIdtTable (PeiServices);
|
||||
//
|
||||
// Since we are at dispatch level, only the Core's private data
|
||||
// is preserved, nobody else should have any data on the stack.
|
||||
// So we need to copy PEI core instance data to memory.
|
||||
//
|
||||
PrivateInMem = AllocateCopyPool (sizeof (PEI_CORE_INSTANCE), Private);
|
||||
ASSERT (PrivateInMem != NULL);
|
||||
|
||||
//
|
||||
// Shadow PEI Core. When permanent memory is avaiable, shadow
|
||||
// PEI Core and PEIMs to get high performance.
|
||||
//
|
||||
PeiCoreFileHandle = NULL;
|
||||
//
|
||||
// Find the PEI Core in the BFV
|
||||
//
|
||||
Status = PeiFindFileEx (
|
||||
(EFI_PEI_FV_HANDLE)Private->Fv[0].FvHeader,
|
||||
NULL,
|
||||
EFI_FV_FILETYPE_PEI_CORE,
|
||||
&PeiCoreFileHandle,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Shadow PEI Core into memory so it will run faster
|
||||
//
|
||||
Status = PeiLoadImage (PeiServices, PeiCoreFileHandle, &EntryPoint, &AuthenticationState);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Switch to memory based stack and reenter PEI Core that has been
|
||||
// shadowed to memory.
|
||||
//
|
||||
//
|
||||
// Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT
|
||||
//
|
||||
TopOfStack = (VOID *)((UINTN)Private->StackBase + (UINTN)Private->StackSize - CPU_STACK_ALIGNMENT);
|
||||
TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
|
||||
|
||||
PeiCoreParameters.SecCoreData = SecCoreData;
|
||||
PeiCoreParameters.PpiList = NULL;
|
||||
PeiCoreParameters.Data = PrivateInMem;
|
||||
ASSERT (PeiCoreParameters.Data != 0);
|
||||
|
||||
PeiSwitchStacks (
|
||||
InvokePeiCore,
|
||||
(VOID*) (UINTN) PeiCore,
|
||||
(VOID*) &PeiCoreParameters,
|
||||
TopOfStack,
|
||||
(VOID*)(UINTN)Private->StackBase
|
||||
);
|
||||
}
|
||||
|
||||
if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \
|
||||
(Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
|
||||
//
|
||||
// If memory is availble we shadow images by default for performance reasons.
|
||||
// We call the entry point a 2nd time so the module knows it's shadowed.
|
||||
//
|
||||
//PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
|
||||
PeimEntryPoint (PeimFileHandle, PeiServices);
|
||||
//PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
|
||||
|
||||
//
|
||||
// PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
|
||||
//
|
||||
Private->Fv[FvCount].PeimState[PeimCount]++;
|
||||
|
||||
//
|
||||
// Process the Notify list and dispatch any notifies for
|
||||
// newly installed PPIs.
|
||||
//
|
||||
ProcessNotifyList (&PrivateData->PS);
|
||||
|
||||
//
|
||||
// If real system memory was discovered and installed by this
|
||||
// PEIM, switch the stacks to the new memory. Since we are
|
||||
// at dispatch level, only the Core's private data is preserved,
|
||||
// nobody else should have any data on the stack.
|
||||
//
|
||||
if (PrivateData->SwitchStackSignal) {
|
||||
//
|
||||
// Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT
|
||||
//
|
||||
TopOfStack = (VOID *)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize - CPU_STACK_ALIGNMENT);
|
||||
TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
|
||||
|
||||
PeiCoreParameters.SecCoreData = SecCoreData;
|
||||
PeiCoreParameters.PpiList = NULL;
|
||||
PeiCoreParameters.Data = TransferOldDataToNewDataRange (PrivateData);
|
||||
ASSERT (PeiCoreParameters.Data != 0);
|
||||
|
||||
PeiSwitchStacks (
|
||||
InvokePeiCore,
|
||||
(VOID*) (UINTN) PeiCore,
|
||||
(VOID*) &PeiCoreParameters,
|
||||
TopOfStack,
|
||||
(VOID*)(UINTN)PrivateData->StackBase
|
||||
);
|
||||
}
|
||||
ProcessNotifyList (Private);
|
||||
}
|
||||
}
|
||||
}
|
||||
DispatchData->CurrentPeim++;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
//
|
||||
// If we could not find another PEIM in the current FV, go try
|
||||
// the FindFv PPI to look in other FVs for more PEIMs. If we can
|
||||
// not locate the FindFv PPI, or if the FindFv PPI can not find
|
||||
// anymore FVs, then exit the PEIM search loop.
|
||||
//
|
||||
if (DispatchData->FindFv == NULL) {
|
||||
Status = PeiServicesLocatePpi (
|
||||
&gEfiFindFvPpiGuid,
|
||||
0,
|
||||
NULL,
|
||||
(VOID **)&DispatchData->FindFv
|
||||
);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
NextFvFound = FALSE;
|
||||
while (!NextFvFound) {
|
||||
Status = DispatchData->FindFv->FindFv (
|
||||
DispatchData->FindFv,
|
||||
&PrivateData->PS,
|
||||
&DispatchData->CurrentFv,
|
||||
&NextFvAddress
|
||||
);
|
||||
//
|
||||
// if there is no next fv, get out of this loop of finding FVs
|
||||
//
|
||||
if (Status != EFI_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
//
|
||||
// don't process the default Fv again. (we don't know the order in which the hobs were created)
|
||||
//
|
||||
if ((NextFvAddress != DefaultFvAddress) &&
|
||||
(NextFvAddress != DispatchData->CurrentFvAddress)) {
|
||||
|
||||
//
|
||||
// VerifyFv() is currently returns SUCCESS all the time, add code to it to
|
||||
// actually verify the given FV
|
||||
//
|
||||
Status = VerifyFv (NextFvAddress);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
NextFvFound = TRUE;
|
||||
DispatchData->CurrentFvAddress = NextFvAddress;
|
||||
DispatchData->CurrentPeimAddress = NULL;
|
||||
//
|
||||
// current PRIM number (CurrentPeim) must continue as is, don't reset it here
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// if there is no next fv, get out of this loop of dispatching PEIMs
|
||||
//
|
||||
if (!NextFvFound) {
|
||||
break;
|
||||
}
|
||||
//
|
||||
// continue in the inner for(;;) loop with a new FV;
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// We set to NULL here to optimize the 2nd entry to this routine after
|
||||
// memory is found. This reprevents rescanning of the FV. We set to
|
||||
// NULL here so we start at the begining of the next FV
|
||||
//
|
||||
Private->CurrentFileHandle = NULL;
|
||||
Private->CurrentPeimCount = 0;
|
||||
//
|
||||
// Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
|
||||
//
|
||||
SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);
|
||||
}
|
||||
|
||||
//
|
||||
// If all the PEIMs that we have found have been dispatched, then
|
||||
// there is nothing left to dispatch and we don't need to go search
|
||||
// through all PEIMs again.
|
||||
// Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
|
||||
// through all the FV.
|
||||
//
|
||||
if ((~(DispatchData->DispatchedPeimBitMap) &
|
||||
((1 << DispatchData->CurrentPeim)-1)) == 0) {
|
||||
break;
|
||||
}
|
||||
Private->CurrentPeimFvCount = 0;
|
||||
|
||||
//
|
||||
// Check if no more PEIMs that depex was satisfied
|
||||
// PeimNeedingDispatch being TRUE means we found a PEIM that did not get
|
||||
// dispatched. So we need to make another pass
|
||||
//
|
||||
if (DispatchData->DispatchedPeimBitMap == DispatchData->PreviousPeimBitMap) {
|
||||
break;
|
||||
}
|
||||
// PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this
|
||||
// pass. If we did not dispatch a PEIM there is no point in trying again
|
||||
// as it will fail the next time too (nothing has changed).
|
||||
//
|
||||
} while (PeimNeedingDispatch && PeimDispatchOnThisPass);
|
||||
|
||||
//
|
||||
// Case when Depex is not satisfied and has to traverse the list again
|
||||
//
|
||||
DispatchData->CurrentPeim = 0;
|
||||
DispatchData->CurrentPeimAddress = 0;
|
||||
DispatchData->PreviousPeimBitMap = DispatchData->DispatchedPeimBitMap;
|
||||
|
||||
//
|
||||
// don't go back to the loop without making sure that the CurrentFvAddress is the
|
||||
// same as the 1st (or default) FV we started with. otherwise we will interpret the bimap wrongly and
|
||||
// mess it up, always start processing the PEIMs from the default FV just like in the first time around.
|
||||
//
|
||||
DispatchData->CurrentFv = 0;
|
||||
DispatchData->CurrentFvAddress = DefaultFvAddress;
|
||||
}
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
//
|
||||
// Debug data for uninstalled Peim list
|
||||
//
|
||||
UINT32 DebugNotDispatchedBitmap;
|
||||
UINT8 DebugFoundPeimPoint;
|
||||
|
||||
DebugFoundPeimPoint = 0;
|
||||
//
|
||||
// Get bitmap of Peims that were not dispatched,
|
||||
//
|
||||
|
||||
DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ ((1 << DispatchData->CurrentPeim)-1));
|
||||
//
|
||||
// Scan bitmap of Peims not installed and print GUIDS
|
||||
//
|
||||
while (DebugNotDispatchedBitmap != 0) {
|
||||
if ((DebugNotDispatchedBitmap & 1) != 0) {
|
||||
DEBUG ((EFI_D_INFO, "WARNING -> InstallPpi: Not Installed: %g\n",
|
||||
&DebugFoundPeimList[DebugFoundPeimPoint]
|
||||
));
|
||||
}
|
||||
DebugFoundPeimPoint++;
|
||||
DebugNotDispatchedBitmap >>= 1;
|
||||
}
|
||||
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
VOID
|
||||
InitializeDispatcherData (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN PEI_CORE_INSTANCE *PrivateData,
|
||||
IN PEI_CORE_INSTANCE *OldCoreData,
|
||||
IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
|
||||
)
|
||||
@@ -395,87 +530,19 @@ Returns:
|
||||
|
||||
--*/
|
||||
{
|
||||
PEI_CORE_INSTANCE *PrivateData;
|
||||
|
||||
PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
|
||||
|
||||
if (OldCoreData == NULL) {
|
||||
PrivateData->DispatchData.CurrentFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase;
|
||||
PrivateData->DispatchData.BootFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase;
|
||||
} else {
|
||||
|
||||
//
|
||||
// Current peim has been dispatched, but not count
|
||||
//
|
||||
PrivateData->DispatchData.CurrentPeim = (UINT8)(OldCoreData->DispatchData.CurrentPeim + 1);
|
||||
PeiInitializeFv (PrivateData, SecCoreData);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
Dispatched (
|
||||
IN UINT8 CurrentPeim,
|
||||
IN UINT32 DispatchedPeimBitMap
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine checks to see if a particular PEIM has been dispatched during
|
||||
the PEI core dispatch.
|
||||
|
||||
Arguments:
|
||||
CurrentPeim - The PEIM/FV in the bit array to check.
|
||||
DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.
|
||||
|
||||
Returns:
|
||||
TRUE - PEIM already dispatched
|
||||
FALSE - Otherwise
|
||||
|
||||
--*/
|
||||
{
|
||||
return (BOOLEAN)((DispatchedPeimBitMap & (1 << CurrentPeim)) != 0);
|
||||
}
|
||||
|
||||
VOID
|
||||
SetDispatched (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN UINT8 CurrentPeim,
|
||||
OUT UINT32 *DispatchedPeimBitMap
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine sets a PEIM as having been dispatched once its entry
|
||||
point has been invoked.
|
||||
|
||||
Arguments:
|
||||
|
||||
PeiServices - The PEI core services table.
|
||||
CurrentPeim - The PEIM/FV in the bit array to check.
|
||||
DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Check if the total number of PEIMs exceed the bitmap.
|
||||
// CurrentPeim is 0-based
|
||||
//
|
||||
ASSERT (CurrentPeim < (sizeof (*DispatchedPeimBitMap) * 8));
|
||||
*DispatchedPeimBitMap |= (1 << CurrentPeim);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
DepexSatisfied (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN VOID *CurrentPeimAddress
|
||||
IN PEI_CORE_INSTANCE *Private,
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN UINTN PeimCount
|
||||
)
|
||||
/*++
|
||||
|
||||
@@ -495,59 +562,27 @@ Returns:
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
INT8 *DepexData;
|
||||
BOOLEAN Runnable;
|
||||
VOID *DepexData;
|
||||
|
||||
Status = PeiServicesFfsFindSectionData (
|
||||
EFI_SECTION_PEI_DEPEX,
|
||||
CurrentPeimAddress,
|
||||
(VOID **)&DepexData
|
||||
);
|
||||
//
|
||||
// If there is no DEPEX, assume the module can be executed
|
||||
//
|
||||
if (PeimCount < Private->AprioriCount) {
|
||||
//
|
||||
// If its in the A priori file then we set Depex to TRUE
|
||||
//
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Status = PeiServicesFfsFindSectionData (EFI_SECTION_PEI_DEPEX, FileHandle, (VOID **) &DepexData);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// If there is no DEPEX, assume the module can be executed
|
||||
//
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Evaluate a given DEPEX
|
||||
//
|
||||
Status = PeimDispatchReadiness (
|
||||
PeiServices,
|
||||
DepexData,
|
||||
&Runnable
|
||||
);
|
||||
|
||||
return Runnable;
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID *
|
||||
TransferOldDataToNewDataRange (
|
||||
IN PEI_CORE_INSTANCE *PrivateData
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine transfers the contents of the pre-permanent memory
|
||||
PEI Core private data to a post-permanent memory data location.
|
||||
|
||||
Arguments:
|
||||
|
||||
PrivateData - Pointer to the current PEI Core private data pre-permanent memory
|
||||
|
||||
Returns:
|
||||
|
||||
Pointer to the PrivateData once the private data has been transferred to permanent memory
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
//Build private HOB to PEI core to transfer old NEM-range data to new NEM-range
|
||||
//
|
||||
return BuildGuidDataHob (&gEfiPeiCorePrivateGuid, PrivateData, sizeof (PEI_CORE_INSTANCE));
|
||||
return PeimDispatchReadiness (&Private->PS, DepexData);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -589,6 +624,7 @@ PeiRegisterForShadow (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This routine invoke the PeiCore's entry in new stack environment.
|
||||
|
||||
@@ -627,7 +663,3 @@ InvokePeiCore (
|
||||
//
|
||||
ASSERT_EFI_ERROR (FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user