-/*++\r
+/** @file\r
\r
Copyright (c) 2006, Intel Corporation\r
All rights reserved. This program and the accompanying materials\r
\r
Revision History\r
\r
---*/\r
+**/\r
+\r
+#include <PeiMain.h>\r
\r
//\r
-// Include common header file for this module.\r
+//CAR is filled with this initial value during SEC phase\r
//\r
-#include "CommonHeader.h"\r
+#define INIT_CAR_VALUE 0x5AA55AA5\r
\r
-#include <PeiMain.h>\r
+typedef struct {\r
+ EFI_STATUS_CODE_DATA DataHeader;\r
+ EFI_HANDLE Handle;\r
+} PEIM_FILE_HANDLE_EXTENDED_DATA;\r
\r
-STATIC\r
-VOID *\r
-TransferOldDataToNewDataRange (\r
- IN PEI_CORE_INSTANCE *PrivateData\r
- );\r
+VOID\r
+DiscoverPeimsAndOrderWithApriori (\r
+ IN PEI_CORE_INSTANCE *Private,\r
+ IN EFI_PEI_FV_HANDLE VolumeHandle\r
+ )\r
+/*++\r
\r
-EFI_STATUS\r
+Routine Description:\r
+\r
+ Discover all Peims and optional Apriori file in one FV. There is at most one\r
+ Apriori file in one FV.\r
+\r
+Arguments:\r
+\r
+ Private - Pointer to the private data passed in from caller\r
+ VolumeHandle - Fv handle.\r
+Returns:\r
+\r
+ NONE\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PEI_FV_HANDLE FileHandle;\r
+ EFI_PEI_FILE_HANDLE AprioriFileHandle;\r
+ EFI_GUID *Apriori;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINTN PeimIndex;\r
+ UINTN PeimCount;\r
+ EFI_GUID *Guid;\r
+ EFI_PEI_FV_HANDLE TempFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
+ EFI_GUID FileGuid[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];\r
+\r
+ //\r
+ // Walk the FV and find all the PEIMs and the Apriori file.\r
+ //\r
+ AprioriFileHandle = NULL;\r
+ Private->CurrentFvFileHandles[0] = NULL;\r
+ Guid = NULL;\r
+ FileHandle = NULL;\r
+\r
+ //\r
+ // If the current Fv has been scanned, directly get its cachable record.\r
+ //\r
+ if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {\r
+ CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Go ahead to scan this Fv, and cache FileHandles within it.\r
+ //\r
+ for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {\r
+ Status = PeiFindFileEx (\r
+ VolumeHandle,\r
+ NULL,\r
+ PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,\r
+ &FileHandle,\r
+ &AprioriFileHandle\r
+ );\r
+ if (Status != EFI_SUCCESS) {\r
+ break;\r
+ }\r
+\r
+ Private->CurrentFvFileHandles[PeimCount] = FileHandle;\r
+ }\r
+\r
+ Private->AprioriCount = 0;\r
+ if (AprioriFileHandle != NULL) {\r
+ //\r
+ // Read the Apriori file\r
+ //\r
+ Status = PeiServicesFfsFindSectionData (EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Calculate the number of PEIMs in the A Priori list\r
+ //\r
+ Private->AprioriCount = *(UINT32 *)(((EFI_FFS_FILE_HEADER *)AprioriFileHandle)->Size) & 0x00FFFFFF;\r
+ Private->AprioriCount -= sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_COMMON_SECTION_HEADER);\r
+ Private->AprioriCount /= sizeof (EFI_GUID);\r
+\r
+ SetMem (FileGuid, sizeof (FileGuid), 0);\r
+ for (Index = 0; Index < PeimCount; Index++) {\r
+ //\r
+ // Make an array of file name guids that matches the FileHandle array so we can convert\r
+ // quickly from file name to file handle\r
+ //\r
+ CopyMem (&FileGuid[Index], &((EFI_FFS_FILE_HEADER *)Private->CurrentFvFileHandles[Index])->Name,sizeof(EFI_GUID));\r
+ }\r
+\r
+ //\r
+ // Walk through FileGuid array to find out who is invalid PEIM guid in Apriori file.\r
+ // Add avalible PEIMs in Apriori file into TempFileHandles array at first.\r
+ //\r
+ Index2 = 0;\r
+ for (Index = 0; Index2 < Private->AprioriCount; Index++) {\r
+ while (Index2 < Private->AprioriCount) {\r
+ Guid = ScanGuid (FileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2++]);\r
+ if (Guid != NULL) {\r
+ break;\r
+ }\r
+ }\r
+ if (Guid == NULL) {\r
+ break;\r
+ }\r
+ PeimIndex = ((UINTN)Guid - (UINTN)&FileGuid[0])/sizeof (EFI_GUID);\r
+ TempFileHandles[Index] = Private->CurrentFvFileHandles[PeimIndex];\r
+\r
+ //\r
+ // Since we have copied the file handle we can remove it from this list.\r
+ //\r
+ Private->CurrentFvFileHandles[PeimIndex] = NULL;\r
+ }\r
+\r
+ //\r
+ // Update valid Aprioricount\r
+ //\r
+ Private->AprioriCount = Index;\r
+\r
+ //\r
+ // Add in any PEIMs not in the Apriori file\r
+ //\r
+ for (;Index < PeimCount; Index++) {\r
+ for (Index2 = 0; Index2 < PeimCount; Index2++) {\r
+ if (Private->CurrentFvFileHandles[Index2] != NULL) {\r
+ TempFileHandles[Index] = Private->CurrentFvFileHandles[Index2];\r
+ Private->CurrentFvFileHandles[Index2] = NULL;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ //Index the end of array contains re-range Pei moudle.\r
+ //\r
+ TempFileHandles[Index] = NULL;\r
+\r
+ //\r
+ // Private->CurrentFvFileHandles is currently in PEIM in the FV order.\r
+ // We need to update it to start with files in the A Priori list and\r
+ // then the remaining files in PEIM order.\r
+ //\r
+ CopyMem (Private->CurrentFvFileHandles, TempFileHandles, sizeof (Private->CurrentFvFileHandles));\r
+ }\r
+ }\r
+ //\r
+ // Cache the current Fv File Handle. So that we don't have to scan the Fv again.\r
+ // Instead, we can retrieve the file handles within this Fv from cachable data.\r
+ //\r
+ Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;\r
+ CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));\r
+\r
+}\r
+\r
+VOID*\r
+ShadowPeiCore(\r
+ EFI_PEI_SERVICES **PeiServices,\r
+ PEI_CORE_INSTANCE *PrivateInMem\r
+ )\r
+{\r
+ EFI_PEI_FILE_HANDLE PeiCoreFileHandle;\r
+ EFI_PHYSICAL_ADDRESS EntryPoint;\r
+ EFI_STATUS Status;\r
+ UINT32 AuthenticationState;\r
+\r
+ PeiCoreFileHandle = NULL;\r
+\r
+ //\r
+ // Find the PEI Core in the BFV\r
+ //\r
+ Status = PeiFindFileEx (\r
+ (EFI_PEI_FV_HANDLE)PrivateInMem->Fv[0].FvHeader,\r
+ NULL,\r
+ EFI_FV_FILETYPE_PEI_CORE,\r
+ &PeiCoreFileHandle,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Shadow PEI Core into memory so it will run faster\r
+ //\r
+ Status = PeiLoadImage (\r
+ PeiServices,\r
+ *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),\r
+ &EntryPoint,\r
+ &AuthenticationState\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);\r
+}\r
+\r
+VOID\r
PeiDispatcher (\r
- IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,\r
- IN PEI_CORE_INSTANCE *PrivateData,\r
- IN PEI_CORE_DISPATCH_DATA *DispatchData\r
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,\r
+ IN PEI_CORE_INSTANCE *Private\r
)\r
\r
/*++\r
\r
Arguments:\r
\r
- PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR\r
+ SecCoreData - Points to a data structure containing information about the PEI core's operating\r
+ environment, such as the size and location of temporary RAM, the stack location and\r
+ the BFV location.\r
PrivateData - Pointer to the private data passed in from caller\r
DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data.\r
\r
\r
--*/\r
{\r
- EFI_STATUS Status;\r
- PEI_CORE_TEMP_POINTERS TempPtr;\r
- UINTN PrivateDataInMem;\r
- BOOLEAN NextFvFound;\r
- EFI_FIRMWARE_VOLUME_HEADER *NextFvAddress;\r
- EFI_FIRMWARE_VOLUME_HEADER *DefaultFvAddress;\r
- VOID *TopOfStack;\r
- //\r
- // Debug data for uninstalled Peim list\r
- //\r
- EFI_GUID DebugFoundPeimList[32];\r
- EFI_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;\r
+ EFI_STATUS Status;\r
+ UINT32 Index1;\r
+ UINT32 Index2;\r
+ EFI_PEI_SERVICES **PeiServices;\r
+ EFI_PEI_FV_HANDLE VolumeHandle;\r
+ EFI_PEI_FILE_HANDLE PeimFileHandle;\r
+ UINTN FvCount;\r
+ UINTN PeimCount;\r
+ UINT32 AuthenticationState;\r
+ EFI_PHYSICAL_ADDRESS EntryPoint;\r
+ EFI_PEIM_ENTRY_POINT2 PeimEntryPoint;\r
+ BOOLEAN PeimNeedingDispatch;\r
+ BOOLEAN PeimDispatchOnThisPass;\r
+ UINTN SaveCurrentPeimCount;\r
+ UINTN SaveCurrentFvCount;\r
+ EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;\r
+ PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData;\r
+ EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase;\r
+ TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;\r
+ EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffTable;\r
+ EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffTable;\r
+ INTN Offset;\r
+ PEI_CORE_INSTANCE *PrivateInMem;\r
+ UINT64 NewPeiStackSize;\r
+ UINT64 OldPeiStackSize;\r
+ UINT64 StackGap;\r
+ EFI_FV_FILE_INFO FvFileInfo;\r
+ UINTN OldCheckingTop;\r
+ UINTN OldCheckingBottom;\r
+\r
+\r
+ PeiServices = &Private->PS;\r
+ PeimEntryPoint = NULL;\r
+ PeimFileHandle = NULL;\r
+ EntryPoint = 0;\r
+\r
+ if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+ //\r
+ // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile\r
+ // update the modules' status from PEIM_STATE_REGISITER_FOR_SHADOW to PEIM_STATE_DONE.\r
+ //\r
+ SaveCurrentPeimCount = Private->CurrentPeimCount;\r
+ SaveCurrentFvCount = Private->CurrentPeimFvCount;\r
+ SaveCurrentFileHandle = Private->CurrentFileHandle;\r
+\r
+ for (Index1 = 0; Index1 <= SaveCurrentFvCount; Index1++) {\r
+ for (Index2 = 0; (Index2 < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->Fv[Index1].FvFileHandles[Index2] != NULL); Index2++) {\r
+ if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
+ PeimFileHandle = Private->Fv[Index1].FvFileHandles[Index2];\r
+ Status = PeiLoadImage (\r
+ &Private->PS,\r
+ PeimFileHandle,\r
+ &EntryPoint,\r
+ &AuthenticationState\r
+ );\r
+ if (Status == EFI_SUCCESS) {\r
+ //\r
+ // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
+ //\r
+ Private->Fv[Index1].PeimState[Index2]++;\r
+ Private->CurrentFileHandle = PeimFileHandle;\r
+ Private->CurrentPeimFvCount = Index1;\r
+ Private->CurrentPeimCount = Index2;\r
+ //\r
+ // Call the PEIM entry point\r
+ //\r
+ PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
\r
- //\r
- // save the Current FV Address so that we will not process it again if FindFv returns it later\r
- //\r
- DefaultFvAddress = DispatchData->BootFvAddress;\r
+ PERF_START (0, "PEIM", NULL, 0);\r
+ PeimEntryPoint(PeimFileHandle, (const EFI_PEI_SERVICES **) &Private->PS);\r
+ PERF_END (0, "PEIM", NULL, 0);\r
+ }\r
+\r
+ //\r
+ // Process the Notify list and dispatch any notifies for\r
+ // newly installed PPIs.\r
+ //\r
+ ProcessNotifyList (Private);\r
+ }\r
+ }\r
+ }\r
+ Private->CurrentFileHandle = SaveCurrentFileHandle;\r
+ Private->CurrentPeimFvCount = SaveCurrentFvCount;\r
+ Private->CurrentPeimCount = SaveCurrentPeimCount;\r
+ }\r
\r
//\r
// This is the main dispatch loop. It will search known FVs for PEIMs and\r
// FV where PEIMs are found in the order their dependencies are also\r
// satisfied, this dipatcher should run only once.\r
//\r
- for (;;) {\r
- //\r
- // This is the PEIM search loop. It will scan through all PEIMs it can find\r
- // looking for PEIMs to dispatch, and will dipatch them if they have not\r
- // already been dispatched and all of their dependencies are met.\r
- // If no more PEIMs can be found in this pass through all known FVs,\r
- // then it will break out of this loop.\r
- //\r
- for (;;) {\r
+ do {\r
+ PeimNeedingDispatch = FALSE;\r
+ PeimDispatchOnThisPass = FALSE;\r
\r
- Status = FindNextPeim (\r
- &PrivateData->PS,\r
- DispatchData->CurrentFvAddress,\r
- &DispatchData->CurrentPeimAddress\r
- );\r
+ for (FvCount = Private->CurrentPeimFvCount; FvCount < Private->FvCount; FvCount++) {\r
+ Private->CurrentPeimFvCount = FvCount;\r
+ VolumeHandle = Private->Fv[FvCount].FvHeader;\r
+\r
+ if (Private->CurrentPeimCount == 0) {\r
+ //\r
+ // When going through each FV, at first, search Apriori file to\r
+ // reorder all PEIMs to ensure the PEIMs in Apriori file to get\r
+ // dispatch at first.\r
+ //\r
+ DiscoverPeimsAndOrderWithApriori (Private, VolumeHandle);\r
+ }\r
\r
//\r
- // If we found a PEIM, check if it is dispatched. If so, go to the\r
- // next PEIM. If not, dispatch it if its dependencies are satisfied.\r
- // If its dependencies are not satisfied, go to the next PEIM.\r
+ // Start to dispatch all modules within the current Fv.\r
//\r
- if (Status == EFI_SUCCESS) {\r
-\r
- DEBUG_CODE_BEGIN ();\r
-\r
- //\r
- // Fill list of found Peims for later list of those not installed\r
- //\r
- CopyMem (\r
- &DebugFoundPeimList[DispatchData->CurrentPeim],\r
- &DispatchData->CurrentPeimAddress->Name,\r
- sizeof (EFI_GUID)\r
- );\r
-\r
- DEBUG_CODE_END ();\r
-\r
- if (!Dispatched (\r
- DispatchData->CurrentPeim,\r
- DispatchData->DispatchedPeimBitMap\r
- )) {\r
- if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) {\r
- Status = PeiLoadImage (\r
- &PrivateData->PS,\r
- DispatchData->CurrentPeimAddress,\r
- &TempPtr.Raw\r
- );\r
- if (Status == EFI_SUCCESS) {\r
+ for (PeimCount = Private->CurrentPeimCount;\r
+ (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);\r
+ PeimCount++) {\r
+ Private->CurrentPeimCount = PeimCount;\r
+ PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];\r
+\r
+ if (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_NOT_DISPATCHED) {\r
+ if (!DepexSatisfied (Private, PeimFileHandle, PeimCount)) {\r
+ PeimNeedingDispatch = TRUE;\r
+ } else {\r
+ Status = PeiFfsGetFileInfo (PeimFileHandle, &FvFileInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+ if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+ //\r
+ // For Fv type file, Produce new FV PPI and FV hob\r
+ //\r
+ Status = ProcessFvFile (PeiServices, PeimFileHandle, &AuthenticationState);\r
+ } else {\r
+ //\r
+ // For PEIM driver, Load its entry point\r
+ //\r
+ Status = PeiLoadImage (\r
+ PeiServices,\r
+ PeimFileHandle,\r
+ &EntryPoint,\r
+ &AuthenticationState\r
+ );\r
+ }\r
\r
+ if ((Status == EFI_SUCCESS)) {\r
//\r
// The PEIM has its dependencies satisfied, and its entry point\r
// has been found, so invoke it.\r
//\r
- PERF_START (\r
- (VOID *) (UINTN) (DispatchData->CurrentPeimAddress),\r
- "PEIM",\r
- NULL,\r
- 0\r
- );\r
+ PERF_START (0, "PEIM", NULL, 0);\r
\r
- //\r
- // BUGBUG: Used to be EFI_PEI_REPORT_STATUS_CODE_CODE\r
- //\r
- ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress;\r
+ ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;\r
\r
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
EFI_PROGRESS_CODE,\r
- EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN,\r
+ FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
(VOID *)(&ExtendedData),\r
sizeof (ExtendedData)\r
);\r
\r
- //\r
- // Is this a authentic image\r
- //\r
- Status = VerifyPeim (\r
- &PrivateData->PS,\r
- DispatchData->CurrentPeimAddress\r
- );\r
-\r
- if (Status != EFI_SECURITY_VIOLATION) {\r
-\r
+ Status = VerifyPeim (Private, VolumeHandle, PeimFileHandle);\r
+ if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {\r
//\r
- // BUGBUG: Before enable PI, we need cast EFI_FFS_FILE_HEADER* to EFI_PEI_FILE_HANDLE*\r
- // Because we use new MdePkg's definition, but they are binary compatible in fact.\r
+ // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED\r
//\r
- Status = TempPtr.PeimEntry (\r
- (EFI_PEI_FILE_HANDLE*)DispatchData->CurrentPeimAddress,\r
- &PrivateData->PS\r
- );\r
+ Private->Fv[FvCount].PeimState[PeimCount]++;\r
+\r
+ if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
+ //\r
+ // Call the PEIM entry point for PEIM driver\r
+ //\r
+ PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;\r
+ PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
+ }\r
+\r
+ PeimDispatchOnThisPass = TRUE;\r
}\r
\r
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
EFI_PROGRESS_CODE,\r
- EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END,\r
+ FixedPcdGet32(PcdStatusCodeValuePeimDispatch),\r
(VOID *)(&ExtendedData),\r
sizeof (ExtendedData)\r
);\r
+ PERF_END (0, "PEIM", NULL, 0);\r
\r
- PERF_END ((VOID *) (UINTN) (DispatchData->CurrentPeimAddress), "PEIM", NULL, 0);\r
+ }\r
\r
+ if (Private->SwitchStackSignal) {\r
//\r
- // Mark the PEIM as dispatched so we don't attempt to run it again\r
+ // Before switch stack from CAR to permenent memory, caculate the heap and stack\r
+ // usage in temporary memory for debuging.\r
//\r
- SetDispatched (\r
- &PrivateData->PS,\r
- DispatchData->CurrentPeim,\r
- &DispatchData->DispatchedPeimBitMap\r
- );\r
+ DEBUG_CODE_BEGIN ();\r
+ UINT32 *StackPointer;\r
+ \r
+ for (StackPointer = (UINT32*)SecCoreData->StackBase;\r
+ (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \\r
+ && (*StackPointer == INIT_CAR_VALUE);\r
+ StackPointer ++);\r
+ \r
+ DEBUG ((EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", SecCoreData->TemporaryRamSize));\r
+ DEBUG ((EFI_D_INFO, " CAR stack ever used: %d bytes.\n",\r
+ (SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))\r
+ ));\r
+ DEBUG ((EFI_D_INFO, " CAR heap used: %d bytes.\n",\r
+ ((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom -\r
+ (UINTN) Private->HobList.Raw)\r
+ ));\r
+ DEBUG_CODE_END ();\r
+ \r
+ //\r
+ // Reserve the size of new stack at bottom of physical memory\r
+ //\r
+ OldPeiStackSize = Private->StackSize;\r
+ NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;\r
+ if (FixedPcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {\r
+ Private->StackSize = NewPeiStackSize;\r
+ } else {\r
+ Private->StackSize = FixedPcdGet32(PcdPeiCoreMaxPeiStackSize);\r
+ }\r
\r
//\r
- // Process the Notify list and dispatch any notifies for\r
- // newly installed PPIs.\r
+ // In theory, the size of new stack in permenent memory should large than\r
+ // size of old stack in temporary memory.\r
+ // But if new stack is smaller than the size of old stack, we also reserve\r
+ // the size of old stack at bottom of permenent memory.\r
//\r
- ProcessNotifyList (&PrivateData->PS);\r
+ StackGap = 0;\r
+ if (Private->StackSize > OldPeiStackSize) {\r
+ StackGap = Private->StackSize - OldPeiStackSize;\r
+ }\r
\r
//\r
- // If real system memory was discovered and installed by this\r
- // PEIM, switch the stacks to the new memory. Since we are\r
- // at dispatch level, only the Core's private data is preserved,\r
- // nobody else should have any data on the stack.\r
+ // Update HandOffHob for new installed permenent memory\r
//\r
- if (PrivateData->SwitchStackSignal) {\r
- TempPtr.PeiCore = (PEI_CORE_ENTRY_POINT)PeiCore;\r
- PrivateDataInMem = (UINTN) TransferOldDataToNewDataRange (PrivateData);\r
- ASSERT (PrivateDataInMem != 0);\r
- //\r
- // Adjust the top of stack to be aligned at CPU_STACK_ALIGNMENT\r
- //\r
- TopOfStack = (VOID *)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize - CPU_STACK_ALIGNMENT);\r
- TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
-\r
- PeiSwitchStacks (\r
- (SWITCH_STACK_ENTRY_POINT)(UINTN)TempPtr.Raw,\r
- PeiStartupDescriptor,\r
- (VOID*)PrivateDataInMem,\r
- TopOfStack,\r
- (VOID*)(UINTN)PrivateData->StackBase\r
+ OldHandOffTable = Private->HobList.HandoffInformationTable;\r
+ OldCheckingBottom = (UINTN)OldHandOffTable;\r
+ OldCheckingTop = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize);\r
+\r
+ //\r
+ // The whole temporary memory will be migrated to physical memory.\r
+ // CAUTION: The new base is computed accounding to gap of new stack.\r
+ //\r
+ NewPermenentMemoryBase = Private->PhysicalMemoryBegin + StackGap;\r
+ Offset = (UINTN) NewPermenentMemoryBase - (UINTN) SecCoreData->TemporaryRamBase;\r
+ NewHandOffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + Offset);\r
+ PrivateInMem = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + Offset);\r
+\r
+ //\r
+ // TemporaryRamSupportPpi is produced by platform's SEC\r
+ //\r
+ Status = PeiLocatePpi (\r
+ (CONST EFI_PEI_SERVICES **) PeiServices,\r
+ &gEfiTemporaryRamSupportPpiGuid,\r
+ 0,\r
+ NULL,\r
+ (VOID**)&TemporaryRamSupportPpi\r
+ );\r
+\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ TemporaryRamSupportPpi->TemporaryRamMigration (\r
+ (CONST EFI_PEI_SERVICES **) PeiServices,\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN) SecCoreData->TemporaryRamBase,\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN) NewPermenentMemoryBase,\r
+ SecCoreData->TemporaryRamSize\r
+ );\r
+\r
+ } else {\r
+ CopyMem (\r
+ (VOID*)(UINTN) NewPermenentMemoryBase,\r
+ SecCoreData->TemporaryRamBase,\r
+ SecCoreData->TemporaryRamSize\r
);\r
}\r
- }\r
- }\r
- }\r
- DispatchData->CurrentPeim++;\r
- continue;\r
\r
- } else {\r
\r
- //\r
- // If we could not find another PEIM in the current FV, go try\r
- // the FindFv PPI to look in other FVs for more PEIMs. If we can\r
- // not locate the FindFv PPI, or if the FindFv PPI can not find\r
- // anymore FVs, then exit the PEIM search loop.\r
- //\r
- if (DispatchData->FindFv == NULL) {\r
- Status = PeiServicesLocatePpi (\r
- &gEfiFindFvPpiGuid,\r
- 0,\r
- NULL,\r
- (VOID **)&DispatchData->FindFv\r
- );\r
- if (Status != EFI_SUCCESS) {\r
- break;\r
- }\r
- }\r
- NextFvFound = FALSE;\r
- while (!NextFvFound) {\r
- Status = DispatchData->FindFv->FindFv (\r
- DispatchData->FindFv,\r
- &PrivateData->PS,\r
- &DispatchData->CurrentFv,\r
- &NextFvAddress\r
- );\r
- //\r
- // if there is no next fv, get out of this loop of finding FVs\r
- //\r
- if (Status != EFI_SUCCESS) {\r
- break;\r
- }\r
- //\r
- // don't process the default Fv again. (we don't know the order in which the hobs were created)\r
- //\r
- if ((NextFvAddress != DefaultFvAddress) &&\r
- (NextFvAddress != DispatchData->CurrentFvAddress)) {\r
+ //\r
+ //\r
+ // Fixup the PeiCore's private data\r
+ //\r
+ PrivateInMem->PS = &PrivateInMem->ServiceTableShadow;\r
+ PrivateInMem->CpuIo = &PrivateInMem->ServiceTableShadow.CpuIo;\r
+ PrivateInMem->HobList.Raw = (VOID*) ((UINTN) PrivateInMem->HobList.Raw + Offset);\r
+ PrivateInMem->StackBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)PrivateInMem->PhysicalMemoryBegin + EFI_PAGE_MASK) & ~EFI_PAGE_MASK);\r
+\r
+ PeiServices = &PrivateInMem->PS;\r
+\r
+ //\r
+ // Fixup for PeiService's address\r
+ //\r
+ SetPeiServicesTablePointer(PeiServices);\r
+\r
+ //\r
+ // Update HandOffHob for new installed permenent memory\r
+ //\r
+ NewHandOffTable->EfiEndOfHobList =\r
+ (EFI_PHYSICAL_ADDRESS)((UINTN) NewHandOffTable->EfiEndOfHobList + Offset);\r
+ NewHandOffTable->EfiMemoryTop = PrivateInMem->PhysicalMemoryBegin +\r
+ PrivateInMem->PhysicalMemoryLength;\r
+ NewHandOffTable->EfiMemoryBottom = PrivateInMem->PhysicalMemoryBegin;\r
+ NewHandOffTable->EfiFreeMemoryTop = PrivateInMem->FreePhysicalMemoryTop;\r
+ NewHandOffTable->EfiFreeMemoryBottom = NewHandOffTable->EfiEndOfHobList +\r
+ sizeof (EFI_HOB_GENERIC_HEADER);\r
+\r
+ //\r
+ // We need convert the PPI desciptor's pointer\r
+ //\r
+ ConvertPpiPointers ((CONST EFI_PEI_SERVICES **)PeiServices, \r
+ OldCheckingBottom, \r
+ OldCheckingTop, \r
+ NewHandOffTable);\r
+\r
+ DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%X Length=0x%X\n",\r
+ (UINTN)PrivateInMem->StackBase,\r
+ PrivateInMem->StackSize));\r
+ BuildStackHob (PrivateInMem->StackBase, PrivateInMem->StackSize);\r
+\r
+ //\r
+ // After the whole temporary memory is migrated, then we can allocate page in\r
+ // permenent memory.\r
+ //\r
+ PrivateInMem->PeiMemoryInstalled = TRUE;\r
+\r
+ //\r
+ // Make sure we don't retry the same PEIM that added memory\r
+ //\r
+ PrivateInMem->CurrentPeimCount++;\r
+\r
+ //\r
+ // Shadow PEI Core. When permanent memory is avaiable, shadow\r
+ // PEI Core and PEIMs to get high performance.\r
+ //\r
+ PrivateInMem->ShadowedPeiCore = ShadowPeiCore (\r
+ PeiServices,\r
+ PrivateInMem\r
+ );\r
+ //\r
+ // Process the Notify list and dispatch any notifies for\r
+ // newly installed PPIs.\r
+ //\r
+ ProcessNotifyList (PrivateInMem);\r
+\r
+ //\r
+ // Entry PEI Phase 2\r
+ //\r
+ PeiCore (SecCoreData, NULL, PrivateInMem);\r
+\r
+ //\r
+ // Code should not come here\r
+ //\r
+ ASSERT_EFI_ERROR(FALSE);\r
+ }\r
\r
//\r
- // VerifyFv() is currently returns SUCCESS all the time, add code to it to\r
- // actually verify the given FV\r
+ // Process the Notify list and dispatch any notifies for\r
+ // newly installed PPIs.\r
//\r
- Status = VerifyFv (NextFvAddress);\r
- if (Status == EFI_SUCCESS) {\r
- NextFvFound = TRUE;\r
- DispatchData->CurrentFvAddress = NextFvAddress;\r
- DispatchData->CurrentPeimAddress = NULL;\r
+ ProcessNotifyList (Private);\r
+\r
+ if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \\r
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
+ //\r
+ // If memory is availble we shadow images by default for performance reasons.\r
+ // We call the entry point a 2nd time so the module knows it's shadowed.\r
//\r
- // current PRIM number (CurrentPeim) must continue as is, don't reset it here\r
+ //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);\r
+ PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);\r
+ //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);\r
+\r
+ //\r
+ // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE\r
+ //\r
+ Private->Fv[FvCount].PeimState[PeimCount]++;\r
+\r
+ //\r
+ // Process the Notify list and dispatch any notifies for\r
+ // newly installed PPIs.\r
//\r
+ ProcessNotifyList (Private);\r
}\r
}\r
}\r
- //\r
- // if there is no next fv, get out of this loop of dispatching PEIMs\r
- //\r
- if (!NextFvFound) {\r
- break;\r
- }\r
- //\r
- // continue in the inner for(;;) loop with a new FV;\r
- //\r
}\r
- }\r
\r
- //\r
- // If all the PEIMs that we have found have been dispatched, then\r
- // there is nothing left to dispatch and we don't need to go search\r
- // through all PEIMs again.\r
- //\r
- if ((~(DispatchData->DispatchedPeimBitMap) &\r
- ((1 << DispatchData->CurrentPeim)-1)) == 0) {\r
- break;\r
- }\r
-\r
- //\r
- // Check if no more PEIMs that depex was satisfied\r
- //\r
- if (DispatchData->DispatchedPeimBitMap == DispatchData->PreviousPeimBitMap) {\r
- break;\r
+ //\r
+ // We set to NULL here to optimize the 2nd entry to this routine after\r
+ // memory is found. This reprevents rescanning of the FV. We set to\r
+ // NULL here so we start at the begining of the next FV\r
+ //\r
+ Private->CurrentFileHandle = NULL;\r
+ Private->CurrentPeimCount = 0;\r
+ //\r
+ // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL\r
+ //\r
+ SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);\r
}\r
\r
//\r
- // Case when Depex is not satisfied and has to traverse the list again\r
- //\r
- DispatchData->CurrentPeim = 0;\r
- DispatchData->CurrentPeimAddress = 0;\r
- DispatchData->PreviousPeimBitMap = DispatchData->DispatchedPeimBitMap;\r
-\r
- //\r
- // don't go back to the loop without making sure that the CurrentFvAddress is the\r
- // same as the 1st (or default) FV we started with. otherwise we will interpret the bimap wrongly and\r
- // mess it up, always start processing the PEIMs from the default FV just like in the first time around.\r
+ // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go\r
+ // through all the FV.\r
//\r
- DispatchData->CurrentFv = 0;\r
- DispatchData->CurrentFvAddress = DefaultFvAddress;\r
- }\r
+ Private->CurrentPeimFvCount = 0;\r
\r
- DEBUG_CODE_BEGIN ();\r
- //\r
- // Debug data for uninstalled Peim list\r
//\r
- UINT32 DebugNotDispatchedBitmap;\r
- UINT8 DebugFoundPeimPoint;\r
-\r
- DebugFoundPeimPoint = 0;\r
+ // PeimNeedingDispatch being TRUE means we found a PEIM that did not get\r
+ // dispatched. So we need to make another pass\r
//\r
- // Get bitmap of Peims that were not dispatched,\r
+ // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM on this\r
+ // pass. If we did not dispatch a PEIM there is no point in trying again\r
+ // as it will fail the next time too (nothing has changed).\r
//\r
+ } while (PeimNeedingDispatch && PeimDispatchOnThisPass);\r
\r
- DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ ((1 << DispatchData->CurrentPeim)-1));\r
- //\r
- // Scan bitmap of Peims not installed and print GUIDS\r
- //\r
- while (DebugNotDispatchedBitmap != 0) {\r
- if ((DebugNotDispatchedBitmap & 1) != 0) {\r
- DEBUG ((EFI_D_INFO, "WARNING -> InstallPpi: Not Installed: %g\n",\r
- &DebugFoundPeimList[DebugFoundPeimPoint]\r
- ));\r
- }\r
- DebugFoundPeimPoint++;\r
- DebugNotDispatchedBitmap >>= 1;\r
- }\r
-\r
- DEBUG_CODE_END ();\r
-\r
- return EFI_NOT_FOUND;\r
}\r
\r
VOID\r
InitializeDispatcherData (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_CORE_INSTANCE *PrivateData,\r
IN PEI_CORE_INSTANCE *OldCoreData,\r
- IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor\r
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData\r
)\r
/*++\r
\r
PeiServices - The PEI core services table.\r
OldCoreData - Pointer to old core data (before switching stack).\r
NULL if being run in non-permament memory mode.\r
- PeiStartupDescriptor - Information and services provided by SEC phase.\r
+ SecCoreData - Points to a data structure containing information about the PEI core's operating\r
+ environment, such as the size and location of temporary RAM, the stack location and\r
+ the BFV location.\r
\r
Returns:\r
\r
\r
--*/\r
{\r
- PEI_CORE_INSTANCE *PrivateData;\r
-\r
- PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
-\r
if (OldCoreData == NULL) {\r
- PrivateData->DispatchData.CurrentFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume;\r
- PrivateData->DispatchData.BootFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume;\r
- } else {\r
-\r
- //\r
- // Current peim has been dispatched, but not count\r
- //\r
- PrivateData->DispatchData.CurrentPeim = (UINT8)(OldCoreData->DispatchData.CurrentPeim + 1);\r
+ PeiInitializeFv (PrivateData, SecCoreData);\r
}\r
\r
return;\r
}\r
\r
\r
-BOOLEAN\r
-Dispatched (\r
- IN UINT8 CurrentPeim,\r
- IN UINT32 DispatchedPeimBitMap\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This routine checks to see if a particular PEIM has been dispatched during\r
- the PEI core dispatch.\r
-\r
-Arguments:\r
- CurrentPeim - The PEIM/FV in the bit array to check.\r
- DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.\r
-\r
-Returns:\r
- TRUE - PEIM already dispatched\r
- FALSE - Otherwise\r
-\r
---*/\r
-{\r
- return (BOOLEAN)((DispatchedPeimBitMap & (1 << CurrentPeim)) != 0);\r
-}\r
-\r
-VOID\r
-SetDispatched (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN UINT8 CurrentPeim,\r
- OUT UINT32 *DispatchedPeimBitMap\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This routine sets a PEIM as having been dispatched once its entry\r
- point has been invoked.\r
-\r
-Arguments:\r
-\r
- PeiServices - The PEI core services table.\r
- CurrentPeim - The PEIM/FV in the bit array to check.\r
- DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV.\r
-\r
-Returns:\r
- None\r
-\r
---*/\r
-{\r
- //\r
- // Check if the total number of PEIMs exceed the bitmap.\r
- // CurrentPeim is 0-based\r
- //\r
- ASSERT (CurrentPeim < (sizeof (*DispatchedPeimBitMap) * 8));\r
- *DispatchedPeimBitMap |= (1 << CurrentPeim);\r
- return;\r
-}\r
-\r
BOOLEAN\r
DepexSatisfied (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN VOID *CurrentPeimAddress\r
+ IN PEI_CORE_INSTANCE *Private,\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ IN UINTN PeimCount\r
)\r
/*++\r
\r
\r
--*/\r
{\r
- EFI_STATUS Status;\r
- INT8 *DepexData;\r
- BOOLEAN Runnable;\r
+ EFI_STATUS Status;\r
+ VOID *DepexData;\r
+\r
+ if (PeimCount < Private->AprioriCount) {\r
+ //\r
+ // If its in the A priori file then we set Depex to TRUE\r
+ //\r
+ return TRUE;\r
+ }\r
\r
- Status = PeiServicesFfsFindSectionData (\r
- EFI_SECTION_PEI_DEPEX,\r
- CurrentPeimAddress,\r
- (VOID **)&DepexData\r
- );\r
//\r
- // If there is no DEPEX, assume the module can be executed\r
+ // Depex section not in the encapsulated section.\r
//\r
+ Status = PeiServicesFfsFindSectionData (\r
+ EFI_SECTION_PEI_DEPEX,\r
+ FileHandle,\r
+ (VOID **)&DepexData\r
+ );\r
+\r
if (EFI_ERROR (Status)) {\r
+ //\r
+ // If there is no DEPEX, assume the module can be executed\r
+ //\r
return TRUE;\r
}\r
\r
//\r
// Evaluate a given DEPEX\r
//\r
- Status = PeimDispatchReadiness (\r
- PeiServices,\r
- DepexData,\r
- &Runnable\r
- );\r
-\r
- return Runnable;\r
+ return PeimDispatchReadiness (&Private->PS, DepexData);\r
}\r
\r
-STATIC\r
-VOID *\r
-TransferOldDataToNewDataRange (\r
- IN PEI_CORE_INSTANCE *PrivateData\r
+/**\r
+ This routine enable a PEIM to register itself to shadow when PEI Foundation\r
+ discovery permanent memory.\r
+\r
+ @param FileHandle File handle of a PEIM.\r
+\r
+ @retval EFI_NOT_FOUND The file handle doesn't point to PEIM itself.\r
+ @retval EFI_ALREADY_STARTED Indicate that the PEIM has been registered itself.\r
+ @retval EFI_SUCCESS Successfully to register itself.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiRegisterForShadow (\r
+ IN EFI_PEI_FILE_HANDLE FileHandle\r
)\r
-/*++\r
+{\r
+ PEI_CORE_INSTANCE *Private;\r
+ Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
\r
-Routine Description:\r
+ if (Private->CurrentFileHandle != FileHandle) {\r
+ //\r
+ // The FileHandle must be for the current PEIM\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
\r
- This routine transfers the contents of the pre-permanent memory\r
- PEI Core private data to a post-permanent memory data location.\r
+ if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {\r
+ //\r
+ // If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started\r
+ //\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
\r
-Arguments:\r
+ Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;\r
\r
- PrivateData - Pointer to the current PEI Core private data pre-permanent memory\r
+ return EFI_SUCCESS;\r
+}\r
\r
-Returns:\r
\r
- Pointer to the PrivateData once the private data has been transferred to permanent memory\r
\r
---*/\r
+/**\r
+ Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob.\r
+\r
+ @param PeiServices Pointer to the PEI Core Services Table.\r
+ @param FileHandle File handle of a Fv type file.\r
+ @param AuthenticationState Pointer to attestation authentication state of image.\r
+\r
+\r
+ @retval EFI_NOT_FOUND FV image can't be found.\r
+ @retval EFI_SUCCESS Successfully to process it.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessFvFile (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_FILE_HANDLE FvFileHandle,\r
+ OUT UINT32 *AuthenticationState\r
+ )\r
{\r
+ EFI_STATUS Status;\r
+ EFI_PEI_FV_HANDLE FvImageHandle;\r
+ EFI_FV_INFO FvImageInfo;\r
+ UINT32 FvAlignment;\r
+ VOID *FvBuffer;\r
+ EFI_PEI_HOB_POINTERS HobFv2;\r
+\r
+ FvBuffer = NULL;\r
+ *AuthenticationState = 0;\r
+\r
//\r
- //Build private HOB to PEI core to transfer old NEM-range data to new NEM-range\r
+ // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
+ // been extracted.\r
//\r
- return BuildGuidDataHob (&gEfiPeiCorePrivateGuid, PrivateData, sizeof (PEI_CORE_INSTANCE));\r
-}\r
+ HobFv2.Raw = GetHobList ();\r
+ while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {\r
+ if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) {\r
+ //\r
+ // this FILE has been dispatched, it will not be dispatched again.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+ HobFv2.Raw = GET_NEXT_HOB (HobFv2);\r
+ }\r
\r
+ //\r
+ // Find FvImage in FvFile\r
+ //\r
+ Status = PeiFfsFindSectionData (\r
+ (CONST EFI_PEI_SERVICES **) PeiServices,\r
+ EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
+ FvFileHandle,\r
+ (VOID **)&FvImageHandle\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Collect FvImage Info.\r
+ //\r
+ Status = PeiFfsGetVolumeInfo (FvImageHandle, &FvImageInfo);\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
+ //\r
+ FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16);\r
+ if (FvAlignment < 8) {\r
+ FvAlignment = 8;\r
+ }\r
+ //\r
+ // Check FvImage\r
+ //\r
+ if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) {\r
+ FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment);\r
+ if (FvBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize);\r
+ //\r
+ // Update FvImageInfo after reload FvImage to new aligned memory\r
+ //\r
+ PeiFfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo);\r
+ }\r
+\r
+ //\r
+ // Install FvPpi and Build FvHob\r
+ //\r
+ PiLibInstallFvInfoPpi (\r
+ NULL,\r
+ FvImageInfo.FvStart,\r
+ (UINT32) FvImageInfo.FvSize,\r
+ &(FvImageInfo.FvName),\r
+ &(((EFI_FFS_FILE_HEADER*)FvFileHandle)->Name)\r
+ );\r
+\r
+ //\r
+ // Inform HOB consumer phase, i.e. DXE core, the existance of this FV\r
+ //\r
+ BuildFvHob (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,\r
+ FvImageInfo.FvSize\r
+ );\r
+ //\r
+ // Makes the encapsulated volume show up in DXE phase to skip processing of\r
+ // encapsulated file again.\r
+ //\r
+ BuildFv2Hob (\r
+ (EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,\r
+ FvImageInfo.FvSize,\r
+ &FvImageInfo.FvName,\r
+ &(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name)\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r