X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FPei%2FDispatcher%2FDispatcher.c;h=4c2eac1384e8e29b2578d3659b55beed3573a8c0;hp=ddd149b23e364f4c01270d2ca577e79d39fd7916;hb=HEAD;hpb=4fb720763c32fa4a65c5ee78666553fe458ce212
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index ddd149b23e..3552feda8f 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -1,32 +1,17 @@
/** @file
EFI PEI Core dispatch services
-
-Copyright (c) 2006 - 2010, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PeiMain.h"
-///
-/// temporary memory is filled with this initial value during SEC phase
-///
-#define INIT_CAR_VALUE 0x5AA55AA5
-
-typedef struct {
- EFI_STATUS_CODE_DATA DataHeader;
- EFI_HANDLE Handle;
-} PEIM_FILE_HANDLE_EXTENDED_DATA;
-
/**
- Discover all Peims and optional Apriori file in one FV. There is at most one
+ Discover all PEIMs and optional Apriori file in one FV. There is at most one
Apriori file in one FV.
@@ -36,523 +21,1320 @@ typedef struct {
**/
VOID
DiscoverPeimsAndOrderWithApriori (
- IN PEI_CORE_INSTANCE *Private,
- IN PEI_CORE_FV_HANDLE *CoreFileHandle
+ IN PEI_CORE_INSTANCE *Private,
+ IN PEI_CORE_FV_HANDLE *CoreFileHandle
)
{
- EFI_STATUS Status;
- EFI_PEI_FV_HANDLE FileHandle;
- EFI_PEI_FILE_HANDLE AprioriFileHandle;
- EFI_GUID *Apriori;
- UINTN Index;
- UINTN Index2;
- UINTN PeimIndex;
- UINTN PeimCount;
- EFI_GUID *Guid;
- EFI_PEI_FV_HANDLE TempFileHandles[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];
- EFI_GUID FileGuid[FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)];
- EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
- EFI_FV_FILE_INFO FileInfo;
-
+ EFI_STATUS Status;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ EFI_PEI_FILE_HANDLE AprioriFileHandle;
+ EFI_GUID *Apriori;
+ UINTN Index;
+ UINTN Index2;
+ UINTN PeimIndex;
+ UINTN PeimCount;
+ EFI_GUID *Guid;
+ EFI_PEI_FILE_HANDLE *TempFileHandles;
+ EFI_GUID *TempFileGuid;
+ EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
+ EFI_FV_FILE_INFO FileInfo;
+
FvPpi = CoreFileHandle->FvPpi;
-
+
//
// Walk the FV and find all the PEIMs and the Apriori file.
//
- AprioriFileHandle = NULL;
- Private->CurrentFvFileHandles[0] = NULL;
- Guid = NULL;
- FileHandle = NULL;
+ AprioriFileHandle = NULL;
+ Private->CurrentFvFileHandles = NULL;
+ Guid = NULL;
//
- // If the current Fv has been scanned, directly get its cachable record.
+ // If the current FV has been scanned, directly get its cached records.
//
- if (Private->Fv[Private->CurrentPeimFvCount].ScanFv) {
- CopyMem (Private->CurrentFvFileHandles, Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, sizeof (Private->CurrentFvFileHandles));
+ if (CoreFileHandle->ScanFv) {
+ Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;
return;
}
+ TempFileHandles = Private->TempFileHandles;
+ TempFileGuid = Private->TempFileGuid;
+
//
- // Go ahead to scan this Fv, and cache FileHandles within it.
+ // Go ahead to scan this FV, get PeimCount and cache FileHandles within it to TempFileHandles.
//
- for (PeimCount = 0; PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv); PeimCount++) {
+ PeimCount = 0;
+ FileHandle = NULL;
+ do {
Status = FvPpi->FindFileByType (FvPpi, PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE, CoreFileHandle->FvHandle, &FileHandle);
- if (Status != EFI_SUCCESS) {
- break;
+ if (!EFI_ERROR (Status)) {
+ if (PeimCount >= Private->TempPeimCount) {
+ //
+ // Run out of room, grow the buffer.
+ //
+ TempFileHandles = AllocatePool (
+ sizeof (EFI_PEI_FILE_HANDLE) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP)
+ );
+ ASSERT (TempFileHandles != NULL);
+ CopyMem (
+ TempFileHandles,
+ Private->TempFileHandles,
+ sizeof (EFI_PEI_FILE_HANDLE) * Private->TempPeimCount
+ );
+ Private->TempFileHandles = TempFileHandles;
+ TempFileGuid = AllocatePool (
+ sizeof (EFI_GUID) * (Private->TempPeimCount + TEMP_FILE_GROWTH_STEP)
+ );
+ ASSERT (TempFileGuid != NULL);
+ CopyMem (
+ TempFileGuid,
+ Private->TempFileGuid,
+ sizeof (EFI_GUID) * Private->TempPeimCount
+ );
+ Private->TempFileGuid = TempFileGuid;
+ Private->TempPeimCount = Private->TempPeimCount + TEMP_FILE_GROWTH_STEP;
+ }
+
+ TempFileHandles[PeimCount++] = FileHandle;
}
+ } while (!EFI_ERROR (Status));
- Private->CurrentFvFileHandles[PeimCount] = FileHandle;
+ DEBUG ((
+ DEBUG_INFO,
+ "%a(): Found 0x%x PEI FFS files in the %dth FV\n",
+ __FUNCTION__,
+ PeimCount,
+ Private->CurrentPeimFvCount
+ ));
+
+ if (PeimCount == 0) {
+ //
+ // No PEIM FFS file is found, set ScanFv flag and return.
+ //
+ CoreFileHandle->ScanFv = TRUE;
+ return;
}
-
+
//
- // Check whether the count of Peims exceeds the max support PEIMs in a FV image
- // If more Peims are required in a FV image, PcdPeiCoreMaxPeimPerFv can be set to a larger value in DSC file.
+ // Record PeimCount, allocate buffer for PeimState and FvFileHandles.
//
- ASSERT (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv));
+ CoreFileHandle->PeimCount = PeimCount;
+ CoreFileHandle->PeimState = AllocateZeroPool (sizeof (UINT8) * PeimCount);
+ ASSERT (CoreFileHandle->PeimState != NULL);
+ CoreFileHandle->FvFileHandles = AllocateZeroPool (sizeof (EFI_PEI_FILE_HANDLE) * PeimCount);
+ ASSERT (CoreFileHandle->FvFileHandles != NULL);
//
// Get Apriori File handle
//
Private->AprioriCount = 0;
- Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);
- if (!EFI_ERROR(Status) && AprioriFileHandle != NULL) {
+ Status = FvPpi->FindFileByName (FvPpi, &gPeiAprioriFileNameGuid, &CoreFileHandle->FvHandle, &AprioriFileHandle);
+ if (!EFI_ERROR (Status) && (AprioriFileHandle != NULL)) {
//
// Read the Apriori file
//
- Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **) &Apriori);
+ Status = FvPpi->FindSectionByType (FvPpi, EFI_SECTION_RAW, AprioriFileHandle, (VOID **)&Apriori);
if (!EFI_ERROR (Status)) {
//
- // Calculate the number of PEIMs in the A Priori list
+ // Calculate the number of PEIMs in the Apriori file
//
Status = FvPpi->GetFileInfo (FvPpi, AprioriFileHandle, &FileInfo);
ASSERT_EFI_ERROR (Status);
- Private->AprioriCount = FileInfo.BufferSize & 0x00FFFFFF;
- Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);
+ Private->AprioriCount = FileInfo.BufferSize;
+ if (IS_SECTION2 (FileInfo.Buffer)) {
+ Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER2);
+ } else {
+ Private->AprioriCount -= sizeof (EFI_COMMON_SECTION_HEADER);
+ }
+
Private->AprioriCount /= sizeof (EFI_GUID);
- ZeroMem (FileGuid, sizeof (FileGuid));
for (Index = 0; Index < PeimCount; Index++) {
//
- // Make an array of file name guids that matches the FileHandle array so we can convert
+ // Make an array of file name GUIDs that matches the FileHandle array so we can convert
// quickly from file name to file handle
//
- Status = FvPpi->GetFileInfo (FvPpi, Private->CurrentFvFileHandles[Index], &FileInfo);
- CopyMem (&FileGuid[Index], &FileInfo.FileName, sizeof(EFI_GUID));
+ Status = FvPpi->GetFileInfo (FvPpi, TempFileHandles[Index], &FileInfo);
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (&TempFileGuid[Index], &FileInfo.FileName, 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.
+ // Walk through TempFileGuid array to find out who is invalid PEIM GUID in Apriori file.
+ // Add available PEIMs in Apriori file into FvFileHandles array.
//
- 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];
+ Index = 0;
+ for (Index2 = 0; Index2 < Private->AprioriCount; Index2++) {
+ Guid = ScanGuid (TempFileGuid, PeimCount * sizeof (EFI_GUID), &Apriori[Index2]);
+ if (Guid != NULL) {
+ PeimIndex = ((UINTN)Guid - (UINTN)&TempFileGuid[0])/sizeof (EFI_GUID);
+ CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[PeimIndex];
- //
- // Since we have copied the file handle we can remove it from this list.
- //
- Private->CurrentFvFileHandles[PeimIndex] = NULL;
+ //
+ // Since we have copied the file handle we can remove it from this list.
+ //
+ TempFileHandles[PeimIndex] = NULL;
+ }
}
//
- // Update valid Aprioricount
+ // 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;
- }
+ for (Index2 = 0; Index2 < PeimCount; Index2++) {
+ if (TempFileHandles[Index2] != NULL) {
+ CoreFileHandle->FvFileHandles[Index++] = TempFileHandles[Index2];
+ TempFileHandles[Index2] = NULL;
}
}
- //
- //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));
+ ASSERT (Index == PeimCount);
}
+ } else {
+ CopyMem (CoreFileHandle->FvFileHandles, TempFileHandles, sizeof (EFI_PEI_FILE_HANDLE) * PeimCount);
}
+
//
- // 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.
+ // The current FV File Handles have been cached. So that we don't have to scan the FV again.
+ // Instead, we can retrieve the file handles within this FV from cached records.
//
- Private->Fv[Private->CurrentPeimFvCount].ScanFv = TRUE;
- CopyMem (Private->Fv[Private->CurrentPeimFvCount].FvFileHandles, Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles));
-
+ CoreFileHandle->ScanFv = TRUE;
+ Private->CurrentFvFileHandles = CoreFileHandle->FvFileHandles;
}
+//
+// This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,
+// This part of memory still need reserved on the very top of memory so that the DXE Core could
+// use these memory for data initialization. This macro should be sync with the same marco
+// defined in DXE Core.
+//
+#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
+
/**
- Shadow PeiCore module from flash to installed memory.
-
- @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
- @param PrivateInMem PeiCore's private data structure
+ This function is to test if the memory range described in resource HOB is available or not.
+
+ This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. Some platform may allocate the
+ memory before PeiLoadFixAddressHook in invoked. so this function is to test if the memory range described by the input resource HOB is
+ available or not.
- @return PeiCore function address after shadowing.
+ @param PrivateData Pointer to the private data passed in from caller
+ @param ResourceHob Pointer to a resource HOB which described the memory range described by the input resource HOB
**/
-VOID*
-ShadowPeiCore(
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN PEI_CORE_INSTANCE *PrivateInMem
+BOOLEAN
+PeiLoadFixAddressIsMemoryRangeAvailable (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob
)
{
- EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
- EFI_PHYSICAL_ADDRESS EntryPoint;
- EFI_STATUS Status;
- UINT32 AuthenticationState;
-
- PeiCoreFileHandle = NULL;
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
+ BOOLEAN IsAvailable;
+ EFI_PEI_HOB_POINTERS Hob;
- //
- // Find the PEI Core in the BFV
- //
- Status = PrivateInMem->Fv[0].FvPpi->FindFileByType (
- PrivateInMem->Fv[0].FvPpi,
- EFI_FV_FILETYPE_PEI_CORE,
- PrivateInMem->Fv[0].FvHandle,
- &PeiCoreFileHandle
- );
- ASSERT_EFI_ERROR (Status);
+ IsAvailable = TRUE;
+ if ((PrivateData == NULL) || (ResourceHob == NULL)) {
+ return FALSE;
+ }
//
- // Shadow PEI Core into memory so it will run faster
+ // test if the memory range describe in the HOB is already allocated.
//
- Status = PeiLoadImage (
- PeiServices,
- *((EFI_PEI_FILE_HANDLE*)&PeiCoreFileHandle),
- PEIM_STATE_REGISITER_FOR_SHADOW,
- &EntryPoint,
- &AuthenticationState
- );
- ASSERT_EFI_ERROR (Status);
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // See if this is a memory allocation HOB
+ //
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
+ MemoryHob = Hob.MemoryAllocation;
+ if ((MemoryHob->AllocDescriptor.MemoryBaseAddress == ResourceHob->PhysicalStart) &&
+ (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength == ResourceHob->PhysicalStart + ResourceHob->ResourceLength))
+ {
+ IsAvailable = FALSE;
+ break;
+ }
+ }
+ }
- //
- // Compute the PeiCore's function address after shaowed PeiCore.
- // _ModuleEntryPoint is PeiCore main function entry
- //
- return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);
+ return IsAvailable;
}
-//
-// This is the minimum memory required by DxeCore initialization. When LMFA feature enabled,
-// This part of memory still need reserved on the very top of memory so that the DXE Core could
-// use these memory for data initialization. This macro should be sync with the same marco
-// defined in DXE Core.
-//
-#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
+
/**
Hook function for Loading Module at Fixed Address feature
-
+
This function should only be invoked when Loading Module at Fixed Address(LMFA) feature is enabled. When feature is
- configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When
- feature is configured as Load Modules at Fixed Offset, the functino is to find the top address which is TOLM-TSEG in general.
- And also the function will re-install PEI memory.
+ configured as Load Modules at Fix Absolute Address, this function is to validate the top address assigned by user. When
+ feature is configured as Load Modules at Fixed Offset, the function is to find the top address which is TOLM-TSEG in general.
+ And also the function will re-install PEI memory.
@param PrivateData Pointer to the private data passed in from caller
**/
VOID
-PeiLoadFixAddressHook(
- IN PEI_CORE_INSTANCE *PrivateData
+PeiLoadFixAddressHook (
+ IN PEI_CORE_INSTANCE *PrivateData
)
{
- EFI_PHYSICAL_ADDRESS TopLoadingAddress;
- UINT64 PeiMemorySize;
- UINT64 TotalReservedMemorySize;
- UINT64 MemoryRangeEnd;
- EFI_PHYSICAL_ADDRESS HighAddress;
- EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
- EFI_HOB_RESOURCE_DESCRIPTOR *NextResourceHob;
- EFI_HOB_RESOURCE_DESCRIPTOR *CurrentResourceHob;
- EFI_PEI_HOB_POINTERS CurrentHob;
- EFI_PEI_HOB_POINTERS Hob;
- EFI_PEI_HOB_POINTERS NextHob;
- EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress;
- UINT64 MaxMemoryLength;
+ EFI_PHYSICAL_ADDRESS TopLoadingAddress;
+ UINT64 PeiMemorySize;
+ UINT64 TotalReservedMemorySize;
+ UINT64 MemoryRangeEnd;
+ EFI_PHYSICAL_ADDRESS HighAddress;
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *NextResourceHob;
+ EFI_HOB_RESOURCE_DESCRIPTOR *CurrentResourceHob;
+ EFI_PEI_HOB_POINTERS CurrentHob;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_PEI_HOB_POINTERS NextHob;
+ EFI_HOB_MEMORY_ALLOCATION *MemoryHob;
+
//
// Initialize Local Variables
//
- CurrentResourceHob = NULL;
- ResourceHob = NULL;
- NextResourceHob = NULL;
- MaxMemoryBaseAddress = 0;
- MaxMemoryLength = 0;
- HighAddress = 0;
- TopLoadingAddress = 0;
- MemoryRangeEnd = 0;
- CurrentHob.Raw = PrivateData->HobList.Raw;
- PeiMemorySize = PrivateData->PhysicalMemoryLength;
+ CurrentResourceHob = NULL;
+ ResourceHob = NULL;
+ NextResourceHob = NULL;
+ HighAddress = 0;
+ TopLoadingAddress = 0;
+ MemoryRangeEnd = 0;
+ CurrentHob.Raw = PrivateData->HobList.Raw;
+ PeiMemorySize = PrivateData->PhysicalMemoryLength;
//
// The top reserved memory include 3 parts: the topest range is for DXE core initialization with the size MINIMUM_INITIAL_MEMORY_SIZE
// then RuntimeCodePage range and Boot time code range.
- //
- TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber));
- TotalReservedMemorySize+= EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)) ;
+ //
+ TotalReservedMemorySize = MINIMUM_INITIAL_MEMORY_SIZE + EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber));
+ TotalReservedMemorySize += EFI_PAGES_TO_SIZE (PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber));
//
// PEI memory range lies below the top reserved memory
- //
+ //
TotalReservedMemorySize += PeiMemorySize;
-
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)));
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)));
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber)));
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize));
+
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber)));
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber)));
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= 0x%x.\n", PcdGet32 (PcdLoadFixAddressPeiCodePageNumber)));
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = 0x%lx.\n", TotalReservedMemorySize));
//
- // Loop through the system memory typed hob to merge the adjacent memory range
+ // Loop through the system memory typed HOB to merge the adjacent memory range
//
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
- //
- // See if this is a resource descriptor HOB
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // See if this is a resource descriptor HOB
//
if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
-
- ResourceHob = Hob.ResourceDescriptor;
+ ResourceHob = Hob.ResourceDescriptor;
//
- // If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.
+ // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.
//
- if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY &&
- ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS) {
+ if ((ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) ||
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS))
+ {
continue;
- }
-
- for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(NextHob); NextHob.Raw = GET_NEXT_HOB(NextHob)) {
- if (NextHob.Raw == Hob.Raw){
+ }
+
+ for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (NextHob); NextHob.Raw = GET_NEXT_HOB (NextHob)) {
+ if (NextHob.Raw == Hob.Raw) {
continue;
- }
+ }
+
//
// See if this is a resource descriptor HOB
//
if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
-
NextResourceHob = NextHob.ResourceDescriptor;
//
// test if range described in this NextResourceHob is system memory and have the same attribute.
// Note: Here is a assumption that system memory should always be healthy even without test.
- //
- if (NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
- (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0)){
-
+ //
+ if ((NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
+ (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0))
+ {
+ //
+ // See if the memory range described in ResourceHob and NextResourceHob is adjacent
+ //
+ if (((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart) &&
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)) ||
+ ((ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart) &&
+ (ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)))
+ {
+ MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength) : (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);
+
+ ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ?
+ ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;
+
+ ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);
+
+ ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);
//
- // See if the memory range described in ResourceHob and NextResourceHob is adjacent
+ // Delete the NextResourceHob by marking it as unused.
//
- if ((ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart &&
- ResourceHob->PhysicalStart + ResourceHob->ResourceLength >= NextResourceHob->PhysicalStart)||
- (ResourceHob->PhysicalStart >= NextResourceHob->PhysicalStart&&
- ResourceHob->PhysicalStart <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) {
-
- MemoryRangeEnd = ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength)>(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength)) ?
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength):(NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength);
-
- ResourceHob->PhysicalStart = (ResourceHob->PhysicalStart < NextResourceHob->PhysicalStart) ?
- ResourceHob->PhysicalStart : NextResourceHob->PhysicalStart;
-
-
- ResourceHob->ResourceLength = (MemoryRangeEnd - ResourceHob->PhysicalStart);
-
- ResourceHob->ResourceAttribute = ResourceHob->ResourceAttribute & (~EFI_RESOURCE_ATTRIBUTE_TESTED);
- //
- // Delete the NextResourceHob by marking it as unused.
- //
- GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;
-
- }
- }
- }
+ GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Some platform is already allocated pages before the HOB re-org. Here to build dedicated resource HOB to describe
+ // the allocated memory range
+ //
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // See if this is a memory allocation HOB
+ //
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
+ MemoryHob = Hob.MemoryAllocation;
+ for (NextHob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (NextHob); NextHob.Raw = GET_NEXT_HOB (NextHob)) {
+ //
+ // See if this is a resource descriptor HOB
+ //
+ if (GET_HOB_TYPE (NextHob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ NextResourceHob = NextHob.ResourceDescriptor;
+ //
+ // If range described in this HOB is not system memory or higher than MAX_ADDRESS, ignored.
+ //
+ if ((NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) || (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS)) {
+ continue;
+ }
+
+ //
+ // If the range describe in memory allocation HOB belongs to the memory range described by the resource HOB
+ //
+ if ((MemoryHob->AllocDescriptor.MemoryBaseAddress >= NextResourceHob->PhysicalStart) &&
+ (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength <= NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength))
+ {
+ //
+ // Build separate resource HOB for this allocated range
+ //
+ if (MemoryHob->AllocDescriptor.MemoryBaseAddress > NextResourceHob->PhysicalStart) {
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ NextResourceHob->ResourceAttribute,
+ NextResourceHob->PhysicalStart,
+ (MemoryHob->AllocDescriptor.MemoryBaseAddress - NextResourceHob->PhysicalStart)
+ );
+ }
+
+ if (MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength < NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength) {
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ NextResourceHob->ResourceAttribute,
+ MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength,
+ (NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength -(MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength))
+ );
+ }
+
+ NextResourceHob->PhysicalStart = MemoryHob->AllocDescriptor.MemoryBaseAddress;
+ NextResourceHob->ResourceLength = MemoryHob->AllocDescriptor.MemoryLength;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Try to find and validate the TOP address.
+ //
+ if ((INT64)PcdGet64 (PcdLoadModuleAtFixAddressEnable) > 0 ) {
+ //
+ // The LMFA feature is enabled as load module at fixed absolute address.
+ //
+ TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdLoadModuleAtFixAddressEnable);
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));
+ //
+ // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range
+ //
+ if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) {
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies
+ //
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // See if this is a resource descriptor HOB
+ //
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ ResourceHob = Hob.ResourceDescriptor;
+ //
+ // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
+ //
+ if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS))
+ {
+ //
+ // See if Top address specified by user is valid.
+ //
+ if ((ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress) &&
+ ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress) &&
+ PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob))
+ {
+ CurrentResourceHob = ResourceHob;
+ CurrentHob = Hob;
+ break;
+ }
+ }
+ }
+ }
+
+ if (CurrentResourceHob != NULL) {
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress));
+ TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE;
+ } else {
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress));
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n"));
+ //
+ // Print the recommended Top address range.
+ //
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // See if this is a resource descriptor HOB
+ //
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ ResourceHob = Hob.ResourceDescriptor;
+ //
+ // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
+ //
+ if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS))
+ {
+ //
+ // See if Top address specified by user is valid.
+ //
+ if ((ResourceHob->ResourceLength > TotalReservedMemorySize) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob)) {
+ DEBUG ((
+ DEBUG_INFO,
+ "(0x%lx, 0x%lx)\n",
+ (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE),
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE)
+ ));
+ }
+ }
+ }
+ }
+
+ //
+ // Assert here
+ //
+ ASSERT (FALSE);
+ return;
+ }
+ } else {
+ //
+ // The LMFA feature is enabled as load module at fixed offset relative to TOLM
+ // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)
+ //
+ //
+ // Search for a tested memory region that is below MAX_ADDRESS
+ //
+ for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ //
+ // See if this is a resource descriptor HOB
+ //
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ ResourceHob = Hob.ResourceDescriptor;
+ //
+ // See if this resource descriptor HOB describes tested system memory below MAX_ADDRESS
+ //
+ if ((ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
+ (ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) &&
+ (ResourceHob->ResourceLength > TotalReservedMemorySize) && PeiLoadFixAddressIsMemoryRangeAvailable (PrivateData, ResourceHob))
+ {
+ //
+ // See if this is the highest largest system memory region below MaxAddress
+ //
+ if (ResourceHob->PhysicalStart > HighAddress) {
+ CurrentResourceHob = ResourceHob;
+ CurrentHob = Hob;
+ HighAddress = CurrentResourceHob->PhysicalStart;
+ }
+ }
+ }
+ }
+
+ if (CurrentResourceHob == NULL) {
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));
+ //
+ // Assert here
+ //
+ ASSERT (FALSE);
+ return;
+ } else {
+ TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength;
+ }
+ }
+
+ if (CurrentResourceHob != NULL) {
+ //
+ // rebuild resource HOB for PEI memory and reserved memory
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_TESTED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ (TopLoadingAddress - TotalReservedMemorySize),
+ TotalReservedMemorySize
+ );
+ //
+ // rebuild resource for the remain memory if necessary
+ //
+ if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ CurrentResourceHob->PhysicalStart,
+ (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart)
+ );
+ }
+
+ if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) {
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
+ ),
+ TopLoadingAddress,
+ (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength - TopLoadingAddress)
+ );
+ }
+
+ //
+ // Delete CurrentHob by marking it as unused since the memory range described by is rebuilt.
+ //
+ GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED;
+ }
+
+ //
+ // Cache the top address for Loading Module at Fixed Address feature
+ //
+ PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData->LoadModuleAtFixAddressTopAddress));
+ //
+ // reinstall the PEI memory relative to TopLoadingAddress
+ //
+ PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;
+ PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;
+}
+
+/**
+ This routine is invoked in switch stack as PeiCore Entry.
+
+ @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 old core data that is used to initialize the
+ core's data areas.
+**/
+VOID
+EFIAPI
+PeiCoreEntry (
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
+ IN PEI_CORE_INSTANCE *Private
+ )
+{
+ //
+ // Entry PEI Phase 2
+ //
+ PeiCore (SecCoreData, NULL, Private);
+}
+
+/**
+ Check SwitchStackSignal and switch stack if SwitchStackSignal is TRUE.
+
+ @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[in] Private Pointer to the private data passed in from caller.
+
+**/
+VOID
+PeiCheckAndSwitchStack (
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData,
+ IN PEI_CORE_INSTANCE *Private
+ )
+{
+ VOID *LoadFixPeiCodeBegin;
+ EFI_STATUS Status;
+ CONST EFI_PEI_SERVICES **PeiServices;
+ UINT64 NewStackSize;
+ 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;
+ EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
+ EFI_PHYSICAL_ADDRESS BaseOfNewHeap;
+ EFI_PHYSICAL_ADDRESS HoleMemBase;
+ UINTN HoleMemSize;
+ UINTN HeapTemporaryRamSize;
+ EFI_PHYSICAL_ADDRESS TempBase1;
+ UINTN TempSize1;
+ EFI_PHYSICAL_ADDRESS TempBase2;
+ UINTN TempSize2;
+ UINTN Index;
+
+ PeiServices = (CONST EFI_PEI_SERVICES **)&Private->Ps;
+
+ if (Private->SwitchStackSignal) {
+ //
+ // Before switch stack from temporary memory to permanent memory, calculate the heap and stack
+ // usage in temporary memory for debugging.
+ //
+ DEBUG_CODE_BEGIN ();
+ UINT32 *StackPointer;
+ EFI_PEI_HOB_POINTERS Hob;
+
+ for ( StackPointer = (UINT32 *)SecCoreData->StackBase;
+ (StackPointer < (UINT32 *)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \
+ && (*StackPointer == PcdGet32 (PcdInitValueInTempStack));
+ StackPointer++)
+ {
+ }
+
+ DEBUG ((DEBUG_INFO, "Temp Stack : BaseAddress=0x%p Length=0x%X\n", SecCoreData->StackBase, (UINT32)SecCoreData->StackSize));
+ DEBUG ((DEBUG_INFO, "Temp Heap : BaseAddress=0x%p Length=0x%X\n", SecCoreData->PeiTemporaryRamBase, (UINT32)SecCoreData->PeiTemporaryRamSize));
+ DEBUG ((DEBUG_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
+ DEBUG ((
+ DEBUG_INFO,
+ " temporary memory stack ever used: %d bytes.\n",
+ (UINT32)(SecCoreData->StackSize - ((UINTN)StackPointer - (UINTN)SecCoreData->StackBase))
+ ));
+ DEBUG ((
+ DEBUG_INFO,
+ " temporary memory heap used for HobList: %d bytes.\n",
+ (UINT32)((UINTN)Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - (UINTN)Private->HobList.Raw)
+ ));
+ DEBUG ((
+ DEBUG_INFO,
+ " temporary memory heap occupied by memory pages: %d bytes.\n",
+ (UINT32)(UINTN)(Private->HobList.HandoffInformationTable->EfiMemoryTop - Private->HobList.HandoffInformationTable->EfiFreeMemoryTop)
+ ));
+ for (Hob.Raw = Private->HobList.Raw; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
+ DEBUG ((
+ DEBUG_INFO,
+ "Memory Allocation 0x%08x 0x%0lx - 0x%0lx\n", \
+ Hob.MemoryAllocation->AllocDescriptor.MemoryType, \
+ Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, \
+ Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress + Hob.MemoryAllocation->AllocDescriptor.MemoryLength - 1
+ ));
+ }
+ }
+
+ DEBUG_CODE_END ();
+
+ if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
+ //
+ // Loading Module at Fixed Address is enabled
+ //
+ PeiLoadFixAddressHook (Private);
+
+ //
+ // If Loading Module at Fixed Address is enabled, Allocating memory range for Pei code range.
+ //
+ LoadFixPeiCodeBegin = AllocatePages ((UINTN)PcdGet32 (PcdLoadFixAddressPeiCodePageNumber));
+ DEBUG ((DEBUG_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = 0x%lX, PeiCodeTop= 0x%lX\n", (UINT64)(UINTN)LoadFixPeiCodeBegin, (UINT64)((UINTN)LoadFixPeiCodeBegin + PcdGet32 (PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE)));
+ }
+
+ //
+ // Reserve the size of new stack at bottom of physical memory
+ //
+ // The size of new stack in permanent memory must be the same size
+ // or larger than the size of old stack in temporary memory.
+ // But if new stack is smaller than the size of old stack, we also reserve
+ // the size of old stack at bottom of permanent memory.
+ //
+ NewStackSize = RShiftU64 (Private->PhysicalMemoryLength, 1);
+ NewStackSize = ALIGN_VALUE (NewStackSize, EFI_PAGE_SIZE);
+ NewStackSize = MIN (PcdGet32 (PcdPeiCoreMaxPeiStackSize), NewStackSize);
+ DEBUG ((DEBUG_INFO, "Old Stack size %d, New stack size %d\n", (UINT32)SecCoreData->StackSize, (UINT32)NewStackSize));
+ ASSERT (NewStackSize >= SecCoreData->StackSize);
+
+ //
+ // Calculate stack offset and heap offset between temporary memory and new permanent
+ // memory separately.
+ //
+ TopOfOldStack = (UINTN)SecCoreData->StackBase + SecCoreData->StackSize;
+ TopOfNewStack = Private->PhysicalMemoryBegin + NewStackSize;
+ if (TopOfNewStack >= TopOfOldStack) {
+ StackOffsetPositive = TRUE;
+ StackOffset = (UINTN)(TopOfNewStack - TopOfOldStack);
+ } else {
+ StackOffsetPositive = FALSE;
+ StackOffset = (UINTN)(TopOfOldStack - TopOfNewStack);
+ }
+
+ Private->StackOffsetPositive = StackOffsetPositive;
+ Private->StackOffset = StackOffset;
+
+ //
+ // Build Stack HOB that describes the permanent memory stack
+ //
+ DEBUG ((DEBUG_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n", TopOfNewStack - NewStackSize, NewStackSize));
+ BuildStackHob (TopOfNewStack - NewStackSize, NewStackSize);
+
+ //
+ // Cache information from SecCoreData into locals before SecCoreData is converted to a permanent memory address
+ //
+ TemporaryRamBase = (EFI_PHYSICAL_ADDRESS)(UINTN)SecCoreData->TemporaryRamBase;
+ TemporaryRamSize = SecCoreData->TemporaryRamSize;
+ TemporaryStackSize = SecCoreData->StackSize;
+ TemporaryStackBase = SecCoreData->StackBase;
+ PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize;
+ PeiTemporaryRamBase = SecCoreData->PeiTemporaryRamBase;
+
+ //
+ // TemporaryRamSupportPpi is produced by platform's SEC
+ //
+ Status = PeiServicesLocatePpi (
+ &gEfiTemporaryRamSupportPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&TemporaryRamSupportPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Heap Offset
+ //
+ BaseOfNewHeap = TopOfNewStack;
+ if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {
+ Private->HeapOffsetPositive = TRUE;
+ Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);
+ } else {
+ Private->HeapOffsetPositive = FALSE;
+ Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);
+ }
+
+ DEBUG ((DEBUG_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64)Private->HeapOffset, (UINT64)Private->StackOffset));
+
+ //
+ // Calculate new HandOffTable and PrivateData address in permanent memory's stack
+ //
+ if (StackOffsetPositive) {
+ SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData + StackOffset);
+ Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private + StackOffset);
+ } else {
+ SecCoreData = (CONST EFI_SEC_PEI_HAND_OFF *)((UINTN)(VOID *)SecCoreData - StackOffset);
+ Private = (PEI_CORE_INSTANCE *)((UINTN)(VOID *)Private - StackOffset);
+ }
+
+ //
+ // Temporary Ram Support PPI is provided by platform, it will copy
+ // temporary memory to permanent memory and do stack switching.
+ // After invoking Temporary Ram Support PPI, the following code's
+ // stack is in permanent memory.
+ //
+ TemporaryRamSupportPpi->TemporaryRamMigration (
+ PeiServices,
+ TemporaryRamBase,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(TopOfNewStack - TemporaryStackSize),
+ TemporaryRamSize
+ );
+
+ //
+ // Migrate memory pages allocated in pre-memory phase.
+ // It could not be called before calling TemporaryRamSupportPpi->TemporaryRamMigration()
+ // as the migrated memory pages may be overridden by TemporaryRamSupportPpi->TemporaryRamMigration().
+ //
+ MigrateMemoryPages (Private, TRUE);
+
+ //
+ // Entry PEI Phase 2
+ //
+ PeiCore (SecCoreData, NULL, Private);
+ } else {
+ //
+ // Migrate memory pages allocated in pre-memory phase.
+ //
+ MigrateMemoryPages (Private, FALSE);
+
+ //
+ // Migrate the PEI Services Table pointer from temporary RAM to permanent RAM.
+ //
+ MigratePeiServicesTablePointer ();
+
+ //
+ // Heap Offset
+ //
+ BaseOfNewHeap = TopOfNewStack;
+ HoleMemBase = TopOfNewStack;
+ HoleMemSize = TemporaryRamSize - PeiTemporaryRamSize - TemporaryStackSize;
+ if (HoleMemSize != 0) {
+ //
+ // Make sure HOB List start address is 8 byte alignment.
+ //
+ BaseOfNewHeap = ALIGN_VALUE (BaseOfNewHeap + HoleMemSize, 8);
+ }
+
+ if (BaseOfNewHeap >= (UINTN)SecCoreData->PeiTemporaryRamBase) {
+ Private->HeapOffsetPositive = TRUE;
+ Private->HeapOffset = (UINTN)(BaseOfNewHeap - (UINTN)SecCoreData->PeiTemporaryRamBase);
+ } else {
+ Private->HeapOffsetPositive = FALSE;
+ Private->HeapOffset = (UINTN)((UINTN)SecCoreData->PeiTemporaryRamBase - BaseOfNewHeap);
+ }
+
+ DEBUG ((DEBUG_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (UINT64)Private->HeapOffset, (UINT64)Private->StackOffset));
+
+ //
+ // Migrate Heap
+ //
+ HeapTemporaryRamSize = (UINTN)(Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom - Private->HobList.HandoffInformationTable->EfiMemoryBottom);
+ ASSERT (BaseOfNewHeap + HeapTemporaryRamSize <= Private->FreePhysicalMemoryTop);
+ CopyMem ((UINT8 *)(UINTN)BaseOfNewHeap, PeiTemporaryRamBase, HeapTemporaryRamSize);
+
+ //
+ // Migrate Stack
+ //
+ CopyMem ((UINT8 *)(UINTN)(TopOfNewStack - TemporaryStackSize), TemporaryStackBase, TemporaryStackSize);
+
+ //
+ // Copy Hole Range Data
+ //
+ if (HoleMemSize != 0) {
+ //
+ // Prepare Hole
+ //
+ if (PeiTemporaryRamBase < TemporaryStackBase) {
+ TempBase1 = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiTemporaryRamBase;
+ TempSize1 = PeiTemporaryRamSize;
+ TempBase2 = (EFI_PHYSICAL_ADDRESS)(UINTN)TemporaryStackBase;
+ TempSize2 = TemporaryStackSize;
+ } else {
+ TempBase1 = (EFI_PHYSICAL_ADDRESS)(UINTN)TemporaryStackBase;
+ TempSize1 = TemporaryStackSize;
+ TempBase2 = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiTemporaryRamBase;
+ TempSize2 = PeiTemporaryRamSize;
+ }
+
+ if (TemporaryRamBase < TempBase1) {
+ Private->HoleData[0].Base = TemporaryRamBase;
+ Private->HoleData[0].Size = (UINTN)(TempBase1 - TemporaryRamBase);
+ }
+
+ if (TempBase1 + TempSize1 < TempBase2) {
+ Private->HoleData[1].Base = TempBase1 + TempSize1;
+ Private->HoleData[1].Size = (UINTN)(TempBase2 - TempBase1 - TempSize1);
+ }
+
+ if (TempBase2 + TempSize2 < TemporaryRamBase + TemporaryRamSize) {
+ Private->HoleData[2].Base = TempBase2 + TempSize2;
+ Private->HoleData[2].Size = (UINTN)(TemporaryRamBase + TemporaryRamSize - TempBase2 - TempSize2);
+ }
+
+ //
+ // Copy Hole Range data.
+ //
+ for (Index = 0; Index < HOLE_MAX_NUMBER; Index++) {
+ if (Private->HoleData[Index].Size > 0) {
+ if (HoleMemBase > Private->HoleData[Index].Base) {
+ Private->HoleData[Index].OffsetPositive = TRUE;
+ Private->HoleData[Index].Offset = (UINTN)(HoleMemBase - Private->HoleData[Index].Base);
+ } else {
+ Private->HoleData[Index].OffsetPositive = FALSE;
+ Private->HoleData[Index].Offset = (UINTN)(Private->HoleData[Index].Base - HoleMemBase);
+ }
+
+ CopyMem ((VOID *)(UINTN)HoleMemBase, (VOID *)(UINTN)Private->HoleData[Index].Base, Private->HoleData[Index].Size);
+ HoleMemBase = HoleMemBase + Private->HoleData[Index].Size;
+ }
+ }
}
- }
+
+ //
+ // Switch new stack
+ //
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)PeiCoreEntry,
+ (VOID *)SecCoreData,
+ (VOID *)Private,
+ (VOID *)(UINTN)TopOfNewStack
+ );
+ }
+
+ //
+ // Code should not come here
+ //
+ ASSERT (FALSE);
}
+}
+
+/**
+ Migrate a PEIM from temporary RAM to permanent memory.
+
+ @param PeimFileHandle Pointer to the FFS file header of the image.
+ @param MigratedFileHandle Pointer to the FFS file header of the migrated image.
+
+ @retval EFI_SUCCESS Successfully migrated the PEIM to permanent memory.
+
+**/
+EFI_STATUS
+EFIAPI
+MigratePeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN EFI_PEI_FILE_HANDLE MigratedFileHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ VOID *Pe32Data;
+ VOID *ImageAddress;
+ CHAR8 *AsciiString;
+ UINTN Index;
+
+ Status = EFI_SUCCESS;
+
+ FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
+ ASSERT (!IS_FFS_FILE2 (FileHeader));
+
+ ImageAddress = NULL;
+ PeiGetPe32Data (MigratedFileHandle, &ImageAddress);
+ if (ImageAddress != NULL) {
+ DEBUG_CODE_BEGIN ();
+ AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);
+ for (Index = 0; AsciiString[Index] != 0; Index++) {
+ if ((AsciiString[Index] == '\\') || (AsciiString[Index] == '/')) {
+ AsciiString = AsciiString + Index + 1;
+ Index = 0;
+ } else if (AsciiString[Index] == '.') {
+ AsciiString[Index] = 0;
+ }
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "%a", AsciiString));
+ DEBUG_CODE_END ();
+
+ Pe32Data = (VOID *)((UINTN)ImageAddress - (UINTN)MigratedFileHandle + (UINTN)FileHandle);
+ Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory.
+
+ @param OrgFvHandle Address of FV handle in temporary memory.
+ @param FvHandle Address of FV handle in permanent memory.
+ @param FvSize Size of the FV.
+
+**/
+VOID
+ConvertStatusCodeCallbacks (
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle,
+ IN UINTN FvSize
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN *NumberOfEntries;
+ UINTN *CallbackEntry;
+ UINTN Index;
+
+ Hob.Raw = GetFirstGuidHob (&gStatusCodeCallbackGuid);
+ while (Hob.Raw != NULL) {
+ NumberOfEntries = GET_GUID_HOB_DATA (Hob);
+ CallbackEntry = NumberOfEntries + 1;
+ for (Index = 0; Index < *NumberOfEntries; Index++) {
+ if (((VOID *)CallbackEntry[Index]) != NULL) {
+ if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) {
+ DEBUG ((
+ DEBUG_INFO,
+ "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ",
+ (UINT64)Index,
+ (sizeof CallbackEntry[Index]) * 2,
+ (UINT64)CallbackEntry[Index]
+ ));
+ if (OrgFvHandle > FvHandle) {
+ CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle);
+ } else {
+ CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "0x%0*Lx\n",
+ (sizeof CallbackEntry[Index]) * 2,
+ (UINT64)CallbackEntry[Index]
+ ));
+ }
+ }
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);
+ }
+}
+
+/**
+ Migrates PEIMs in the given firmware volume.
+
+ @param Private Pointer to the PeiCore's private data structure.
+ @param FvIndex The firmware volume index to migrate.
+ @param OrgFvHandle The handle to the firmware volume in temporary memory.
+ @param FvHandle The handle to the firmware volume in permanent memory.
+
+ @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully
+ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+MigratePeimsInFv (
+ IN PEI_CORE_INSTANCE *Private,
+ IN UINTN FvIndex,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle
+ )
+{
+ EFI_STATUS Status;
+ volatile UINTN FileIndex;
+ EFI_PEI_FILE_HANDLE MigratedFileHandle;
+ EFI_PEI_FILE_HANDLE FileHandle;
+
+ if ((Private == NULL) || (FvIndex >= Private->FvCount)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Private->Fv[FvIndex].ScanFv) {
+ for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) {
+ if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) {
+ FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex];
+
+ MigratedFileHandle = (EFI_PEI_FILE_HANDLE)((UINTN)FileHandle - OrgFvHandle + FvHandle);
+
+ DEBUG ((DEBUG_VERBOSE, " Migrating FileHandle %2d ", FileIndex));
+ Status = MigratePeim (FileHandle, MigratedFileHandle);
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle;
+ if (FvIndex == Private->CurrentPeimFvCount) {
+ Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle;
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Migrate FVs out of temporary RAM before the cache is flushed.
+
+ @param Private PeiCore's private data structure
+ @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.
+
+ @retval EFI_SUCCESS Successfully migrated installed FVs from temporary RAM to permanent memory.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.
+
+**/
+EFI_STATUS
+EFIAPI
+EvacuateTempRam (
+ IN PEI_CORE_INSTANCE *Private,
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
+ )
+{
+ EFI_STATUS Status;
+ volatile UINTN FvIndex;
+ volatile UINTN FvChildIndex;
+ UINTN ChildFvOffset;
+ EFI_PHYSICAL_ADDRESS FvHeaderAddress;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *RawDataFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader;
+
+ PEI_CORE_FV_HANDLE PeiCoreFvHandle;
+ EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;
+ EDKII_MIGRATED_FV_INFO MigratedFvInfo;
+
+ ASSERT (Private->PeiMemoryInstalled);
+
+ DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n"));
+
//
- // Try to find and validate the TOP address.
- //
- if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) > 0 ) {
- //
- // The LMFA feature is enabled as load module at fixed absolute address.
- //
- TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64(PcdLoadModuleAtFixAddressEnable);
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Loading module at fixed absolute address.\n"));
- //
- // validate the Address. Loop the resource descriptor HOB to make sure the address is in valid memory range
- //
- if ((TopLoadingAddress & EFI_PAGE_MASK) != 0) {
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid since top address should be page align. \n", TopLoadingAddress));
- ASSERT (FALSE);
+ // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.
+ //
+ Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **)&Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **)&PeiCoreFvLocationPpi);
+ if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {
+ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE)PeiCoreFvLocationPpi->PeiCoreFvLocation;
+ } else {
+ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE)SecCoreData->BootFirmwareVolumeBase;
+ }
+
+ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
+ if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {
+ CopyMem (&PeiCoreFvHandle, &Private->Fv[FvIndex], sizeof (PEI_CORE_FV_HANDLE));
+ break;
}
- //
- // Search for a memory region that is below MAX_ADDRESS and in which TopLoadingAddress lies
- //
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+ }
+
+ Status = EFI_SUCCESS;
+
+ ConvertPeiCorePpiPointers (Private, &PeiCoreFvHandle);
+
+ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
+ FvHeader = Private->Fv[FvIndex].FvHeader;
+ ASSERT (FvHeader != NULL);
+ ASSERT (FvIndex < Private->FvCount);
+
+ DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN)FvHeader));
+ if (
+ !(
+ ((EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader >= Private->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop)
+ )
+ )
+ {
//
- // See if this is a resource descriptor HOB
+ // Allocate page to save the rebased PEIMs, the PEIMs will get dispatched later.
//
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ EFI_SIZE_TO_PAGES ((UINTN)FvHeader->FvLength),
+ &FvHeaderAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+ MigratedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHeaderAddress;
- ResourceHob = Hob.ResourceDescriptor;
- //
- // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
- //
- if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
- ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {
- //
- // See if Top address specified by user is valid.
- //
- if (ResourceHob->PhysicalStart + TotalReservedMemorySize < TopLoadingAddress &&
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MINIMUM_INITIAL_MEMORY_SIZE) >= TopLoadingAddress) {
- CurrentResourceHob = ResourceHob;
- CurrentHob = Hob;
- break;
- }
- }
- }
- }
- if (CurrentResourceHob != NULL) {
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO:Top Address 0x%lx is valid \n", TopLoadingAddress));
- TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE;
- } else {
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address 0x%lx is invalid \n", TopLoadingAddress));
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The recommended Top Address for the platform is: \n"));
- //
- // Print the recomended Top address range.
- //
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
- //
- // See if this is a resource descriptor HOB
- //
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
-
- ResourceHob = Hob.ResourceDescriptor;
- //
- // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
- //
- if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
- ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS) {
- //
- // See if Top address specified by user is valid.
- //
- if (ResourceHob->ResourceLength > TotalReservedMemorySize) {
- DEBUG ((EFI_D_INFO, "(0x%lx, 0x%lx)\n",
- (ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE),
- (ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE)
- ));
- }
- }
- }
- }
//
- // Assert here
+ // Allocate pool to save the raw PEIMs, which is used to keep consistent context across
+ // multiple boot and PCR0 will keep the same no matter if the address of allocated page is changed.
//
- ASSERT (FALSE);
- }
- } else {
- //
- // The LMFA feature is enabled as load module at fixed offset relative to TOLM
- // Parse the Hob list to find the topest available memory. Generally it is (TOLM - TSEG)
- //
- //
- // Search for a tested memory region that is below MAX_ADDRESS
- //
- for (Hob.Raw = PrivateData->HobList.Raw; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ EFI_SIZE_TO_PAGES ((UINTN)FvHeader->FvLength),
+ &FvHeaderAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+ RawDataFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHeaderAddress;
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " Migrating FV[%d] from 0x%08X to 0x%08X\n",
+ FvIndex,
+ (UINTN)FvHeader,
+ (UINTN)MigratedFvHeader
+ ));
+
//
- // See if this is a resource descriptor HOB
+ // Copy the context to the rebased pages and raw pages, and create hob to save the
+ // information. The MigratedFvInfo HOB will never be produced when
+ // PcdMigrateTemporaryRamFirmwareVolumes is FALSE, because the PCD control the
+ // feature.
//
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
-
- ResourceHob = Hob.ResourceDescriptor;
- //
- // See if this resource descrior HOB describes tested system memory below MAX_ADDRESS
- //
- if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
- ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MAX_ADDRESS &&
- ResourceHob->ResourceLength > TotalReservedMemorySize) {
- //
- // See if this is the highest largest system memory region below MaxAddress
- //
- if (ResourceHob->PhysicalStart > HighAddress) {
- CurrentResourceHob = ResourceHob;
- CurrentHob = Hob;
- HighAddress = CurrentResourceHob->PhysicalStart;
- }
- }
- }
- }
- if (CurrentResourceHob == NULL) {
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:The System Memory is too small\n"));
+ CopyMem (MigratedFvHeader, FvHeader, (UINTN)FvHeader->FvLength);
+ CopyMem (RawDataFvHeader, MigratedFvHeader, (UINTN)FvHeader->FvLength);
+ MigratedFvInfo.FvOrgBase = (UINT32)(UINTN)FvHeader;
+ MigratedFvInfo.FvNewBase = (UINT32)(UINTN)MigratedFvHeader;
+ MigratedFvInfo.FvDataBase = (UINT32)(UINTN)RawDataFvHeader;
+ MigratedFvInfo.FvLength = (UINT32)(UINTN)FvHeader->FvLength;
+ BuildGuidDataHob (&gEdkiiMigratedFvInfoGuid, &MigratedFvInfo, sizeof (MigratedFvInfo));
+
//
- // Assert here
+ // Migrate any children for this FV now
//
- ASSERT (FALSE);
- } else {
- TopLoadingAddress = CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength ;
- }
- }
-
- if (CurrentResourceHob != NULL) {
- //
- // rebuild hob for PEI memmory and reserved memory
- //
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,
- (
- EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_TESTED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
- ),
- (TopLoadingAddress - TotalReservedMemorySize), // MemoryBegin
- TotalReservedMemorySize // MemoryLength
- );
- //
- // rebuild hob for the remain memory if necessary
- //
- if (CurrentResourceHob->PhysicalStart < TopLoadingAddress - TotalReservedMemorySize) {
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType,
- (
- EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
- ),
- CurrentResourceHob->PhysicalStart, // MemoryBegin
- (TopLoadingAddress - TotalReservedMemorySize - CurrentResourceHob->PhysicalStart) // MemoryLength
- );
- }
- if (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength > TopLoadingAddress ) {
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY,
- (
- EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
- ),
- TopLoadingAddress,
- (CurrentResourceHob->PhysicalStart + CurrentResourceHob->ResourceLength - TopLoadingAddress)
- );
+ for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) {
+ ChildFvHeader = Private->Fv[FvChildIndex].FvHeader;
+ if (
+ ((UINTN)ChildFvHeader > (UINTN)FvHeader) &&
+ (((UINTN)ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN)FvHeader) + FvHeader->FvLength)
+ )
+ {
+ DEBUG ((DEBUG_VERBOSE, " Child FV[%02d] is being migrated.\n", FvChildIndex));
+ ChildFvOffset = (UINTN)ChildFvHeader - (UINTN)FvHeader;
+ DEBUG ((DEBUG_VERBOSE, " Child FV offset = 0x%x.\n", ChildFvOffset));
+ MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)MigratedFvHeader + ChildFvOffset);
+ Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader;
+ Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE)MigratedChildFvHeader;
+ DEBUG ((DEBUG_VERBOSE, " Child migrated FV header at 0x%x.\n", (UINTN)MigratedChildFvHeader));
+
+ Status = MigratePeimsInFv (Private, FvChildIndex, (UINTN)ChildFvHeader, (UINTN)MigratedChildFvHeader);
+ ASSERT_EFI_ERROR (Status);
+
+ ConvertPpiPointersFv (
+ Private,
+ (UINTN)ChildFvHeader,
+ (UINTN)MigratedChildFvHeader,
+ (UINTN)ChildFvHeader->FvLength - 1
+ );
+
+ ConvertStatusCodeCallbacks (
+ (UINTN)ChildFvHeader,
+ (UINTN)MigratedChildFvHeader,
+ (UINTN)ChildFvHeader->FvLength - 1
+ );
+
+ ConvertFvHob (Private, (UINTN)ChildFvHeader, (UINTN)MigratedChildFvHeader);
+ }
+ }
+
+ Private->Fv[FvIndex].FvHeader = MigratedFvHeader;
+ Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE)MigratedFvHeader;
+
+ Status = MigratePeimsInFv (Private, FvIndex, (UINTN)FvHeader, (UINTN)MigratedFvHeader);
+ ASSERT_EFI_ERROR (Status);
+
+ ConvertPpiPointersFv (
+ Private,
+ (UINTN)FvHeader,
+ (UINTN)MigratedFvHeader,
+ (UINTN)FvHeader->FvLength - 1
+ );
+
+ ConvertStatusCodeCallbacks (
+ (UINTN)FvHeader,
+ (UINTN)MigratedFvHeader,
+ (UINTN)FvHeader->FvLength - 1
+ );
+
+ ConvertFvHob (Private, (UINTN)FvHeader, (UINTN)MigratedFvHeader);
}
- //
- // Delete CurrentHob by marking it as unused since the the memory range described by is rebuilt.
- //
- GET_HOB_TYPE (CurrentHob) = EFI_HOB_TYPE_UNUSED;
}
- //
- // Cache the top address for Loading Module at Fixed Address feature
- //
- PrivateData->LoadModuleAtFixAddressTopAddress = TopLoadingAddress - MINIMUM_INITIAL_MEMORY_SIZE;
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Top address = 0x%lx\n", PrivateData->LoadModuleAtFixAddressTopAddress));
- //
- // reinstall the PEI memory relative to TopLoadingAddress
- //
- PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;
- PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;
+ RemoveFvHobsInTemporaryMemory (Private);
+
+ return Status;
}
+
/**
Conduct PEIM dispatch.
@@ -568,87 +1350,79 @@ PeiDispatcher (
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;
- PEIM_FILE_HANDLE_EXTENDED_DATA ExtendedData;
- EFI_PHYSICAL_ADDRESS NewPermenentMemoryBase;
- TEMPORARY_RAM_SUPPORT_PPI *TemporaryRamSupportPpi;
- EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffTable;
- EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffTable;
- INTN StackOffset;
- INTN HeapOffset;
- PEI_CORE_INSTANCE *PrivateInMem;
- UINT64 NewPeiStackSize;
- UINT64 OldPeiStackSize;
- UINT64 StackGap;
- EFI_FV_FILE_INFO FvFileInfo;
- UINTN OldCheckingTop;
- UINTN OldCheckingBottom;
- PEI_CORE_FV_HANDLE *CoreFvHandle;
- VOID *LoadFixPeiCodeBegin;
-
- PeiServices = (CONST EFI_PEI_SERVICES **) &Private->Ps;
+ 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)) {
+ if ((Private->PeiMemoryInstalled) &&
+ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (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.
+ // update the modules' status from PEIM_STATE_REGISTER_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 < FixedPcdGet32 (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];
- Status = PeiLoadImage (
- (CONST EFI_PEI_SERVICES **) &Private->Ps,
- PeimFileHandle,
- PEIM_STATE_REGISITER_FOR_SHADOW,
- &EntryPoint,
- &AuthenticationState
- );
+ for (Index1 = 0; Index1 < Private->FvCount; Index1++) {
+ for (Index2 = 0; Index2 < Private->Fv[Index1].PeimCount; Index2++) {
+ if (Private->Fv[Index1].PeimState[Index2] == PEIM_STATE_REGISTER_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_REGISTER_FOR_SHADOW,
+ &EntryPoint,
+ &AuthenticationState
+ );
if (Status == EFI_SUCCESS) {
//
- // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
+ // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
//
Private->Fv[Index1].PeimState[Index2]++;
- Private->CurrentFileHandle = PeimFileHandle;
- Private->CurrentPeimFvCount = Index1;
- Private->CurrentPeimCount = 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);
+ PERF_START_IMAGE_BEGIN (PeimFileHandle);
+ PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **)&Private->Ps);
+ PERF_START_IMAGE_END (PeimFileHandle);
}
//
// Process the Notify list and dispatch any notifies for
// newly installed PPIs.
//
- ProcessNotifyList (Private);
+ ProcessDispatchNotifyList (Private);
}
}
}
+
Private->CurrentFileHandle = SaveCurrentFileHandle;
Private->CurrentPeimFvCount = SaveCurrentFvCount;
Private->CurrentPeimCount = SaveCurrentPeimCount;
@@ -657,33 +1431,33 @@ PeiDispatcher (
//
// 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
+ // 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.
+ // satisfied, this dispatcher should run only once.
//
do {
//
- // In case that reenter PeiCore happens, the last pass record is still available.
+ // In case that reenter PeiCore happens, the last pass record is still available.
//
if (!Private->PeimDispatcherReenter) {
- Private->PeimNeedingDispatch = FALSE;
- Private->PeimDispatchOnThisPass = FALSE;
+ Private->PeimNeedingDispatch = FALSE;
+ Private->PeimDispatchOnThisPass = FALSE;
} else {
- Private->PeimDispatcherReenter = FALSE;
+ 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) {
@@ -696,13 +1470,14 @@ PeiDispatcher (
}
//
- // Start to dispatch all modules within the current Fv.
+ // Start to dispatch all modules within the current FV.
//
for (PeimCount = Private->CurrentPeimCount;
- (PeimCount < FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) && (Private->CurrentFvFileHandles[PeimCount] != NULL);
- PeimCount++) {
- Private->CurrentPeimCount = PeimCount;
- PeimFileHandle = Private->CurrentFileHandle = Private->CurrentFvFileHandles[PeimCount];
+ PeimCount < Private->Fv[FvCount].PeimCount;
+ 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)) {
@@ -712,10 +1487,23 @@ PeiDispatcher (
ASSERT_EFI_ERROR (Status);
if (FvFileInfo.FileType == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
//
- // For Fv type file, Produce new FV PPI and FV hob
+ // For FV type file, Produce new FvInfo PPI and FV HOB
//
- Status = ProcessFvFile (&Private->Fv[FvCount], PeimFileHandle);
- AuthenticationState = 0;
+ 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 {
+ //
+ // The related GuidedSectionExtraction/Decompress PPI for the
+ // encapsulated FV image section may be installed in the rest
+ // of this do-while loop, so need to make another pass.
+ //
+ Private->PeimNeedingDispatch = TRUE;
+ }
} else {
//
// For PEIM driver, Load its entry point
@@ -727,276 +1515,101 @@ PeiDispatcher (
&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);
-
- ExtendedData.Handle = (EFI_HANDLE)PeimFileHandle;
-
- REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
- EFI_PROGRESS_CODE,
- (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
- (VOID *)(&ExtendedData),
- sizeof (ExtendedData)
- );
-
- Status = VerifyPeim (Private, CoreFvHandle->FvHandle, PeimFileHandle);
- if (Status != EFI_SECURITY_VIOLATION && (AuthenticationState == 0)) {
+ if (Status == EFI_SUCCESS) {
//
- // PEIM_STATE_NOT_DISPATCHED move to PEIM_STATE_DISPATCHED
+ // The PEIM has its dependencies satisfied, and its entry point
+ // has been found, so invoke it.
//
- Private->Fv[FvCount].PeimState[PeimCount]++;
+ PERF_START_IMAGE_BEGIN (PeimFileHandle);
- if (FvFileInfo.FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
+ 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);
+ PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **)PeiServices);
+ Private->PeimDispatchOnThisPass = TRUE;
+ } else {
+ //
+ // The related GuidedSectionExtraction PPI for the
+ // signed PEIM image section may be installed in the rest
+ // of this do-while loop, so need to make another pass.
+ //
+ Private->PeimNeedingDispatch = TRUE;
}
- 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_START_IMAGE_END (PeimFileHandle);
}
-
- REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
- EFI_PROGRESS_CODE,
- (EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN),
- (VOID *)(&ExtendedData),
- sizeof (ExtendedData)
- );
- PERF_END (PeimFileHandle, "PEIM", NULL, 0);
-
}
- if (Private->SwitchStackSignal) {
- //
- // Before switch stack from temporary memory to permenent memory, caculate the heap and stack
- // usage in temporary memory for debuging.
- //
- DEBUG_CODE_BEGIN ();
- UINT32 *StackPointer;
-
- for (StackPointer = (UINT32*)SecCoreData->StackBase;
- (StackPointer < (UINT32*)((UINTN)SecCoreData->StackBase + SecCoreData->StackSize)) \
- && (*StackPointer == INIT_CAR_VALUE);
- StackPointer ++);
-
- DEBUG ((EFI_D_INFO, "Total temporary memory: %d bytes.\n", (UINT32)SecCoreData->TemporaryRamSize));
- DEBUG ((EFI_D_INFO, " temporary memory stack ever used: %d bytes.\n",
- (SecCoreData->StackSize - ((UINTN) StackPointer - (UINTN)SecCoreData->StackBase))
- ));
- DEBUG ((EFI_D_INFO, " temporary memory heap used: %d bytes.\n",
- ((UINTN) Private->HobList.HandoffInformationTable->EfiFreeMemoryBottom -
- (UINTN) Private->HobList.Raw)
- ));
- DEBUG_CODE_END ();
-
- if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
- //
- // Loading Module at Fixed Address is enabled
- //
- PeiLoadFixAddressHook(Private);
- //
- // if Loading Module at Fixed Address is enabled, This is the first invoke to page
- // allocation for Pei Code range. This memory range should be reserved for loading PEIMs
- //
- LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));
- DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = 0x%lX, PeiCodeTop= 0x%lX\n", (UINT64)LoadFixPeiCodeBegin, (UINT64)((UINTN)LoadFixPeiCodeBegin + PcdGet32(PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE)));
- }
-
- //
- // Reserve the size of new stack at bottom of physical memory
- //
- OldPeiStackSize = (UINT64) SecCoreData->StackSize;
- NewPeiStackSize = (RShiftU64 (Private->PhysicalMemoryLength, 1) + EFI_PAGE_MASK) & ~EFI_PAGE_MASK;
- if (PcdGet32(PcdPeiCoreMaxPeiStackSize) > (UINT32) NewPeiStackSize) {
- Private->StackSize = NewPeiStackSize;
- } else {
- Private->StackSize = PcdGet32(PcdPeiCoreMaxPeiStackSize);
- }
-
- //
- // In theory, the size of new stack in permenent memory should large than
- // size of old stack in temporary memory.
- // But if new stack is smaller than the size of old stack, we also reserve
- // the size of old stack at bottom of permenent memory.
- //
- DEBUG ((EFI_D_INFO, "Old Stack size %d, New stack size %d\n", (INT32) OldPeiStackSize, (INT32) Private->StackSize));
- ASSERT (Private->StackSize >= OldPeiStackSize);
- StackGap = Private->StackSize - OldPeiStackSize;
-
- //
- // Update HandOffHob for new installed permenent memory
- //
- OldHandOffTable = Private->HobList.HandoffInformationTable;
- OldCheckingBottom = (UINTN)(SecCoreData->TemporaryRamBase);
- OldCheckingTop = (UINTN)(OldCheckingBottom + SecCoreData->TemporaryRamSize);
-
- //
- // The whole temporary memory will be migrated to physical memory.
- // CAUTION: The new base is computed accounding to gap of new stack.
- //
- NewPermenentMemoryBase = Private->PhysicalMemoryBegin + StackGap;
-
- //
- // Caculate stack offset and heap offset between temporary memory and new permement
- // memory seperately.
- //
- StackOffset = (UINTN) NewPermenentMemoryBase - (UINTN) SecCoreData->StackBase;
- HeapOffset = (INTN) ((UINTN) Private->PhysicalMemoryBegin + Private->StackSize - \
- (UINTN) SecCoreData->PeiTemporaryRamBase);
- DEBUG ((EFI_D_INFO, "Heap Offset = 0x%lX Stack Offset = 0x%lX\n", (INT64)HeapOffset, (INT64)StackOffset));
-
- //
- // Caculate new HandOffTable and PrivateData address in permenet memory's stack
- //
- NewHandOffTable = (EFI_HOB_HANDOFF_INFO_TABLE *)((UINTN)OldHandOffTable + HeapOffset);
- PrivateInMem = (PEI_CORE_INSTANCE *)((UINTN) (VOID*) Private + StackOffset);
-
- //
- // TemporaryRamSupportPpi is produced by platform's SEC
- //
- Status = PeiLocatePpi (
- (CONST EFI_PEI_SERVICES **) PeiServices,
- &gEfiTemporaryRamSupportPpiGuid,
- 0,
- NULL,
- (VOID**)&TemporaryRamSupportPpi
- );
-
-
- if (!EFI_ERROR (Status)) {
- //
- // Temporary Ram support Ppi is provided by platform, it will copy
- // temporary memory to permenent memory and do stack switching.
- // After invoken temporary Ram support, following code's stack is in
- // memory but not in temporary memory.
- //
- TemporaryRamSupportPpi->TemporaryRamMigration (
- (CONST EFI_PEI_SERVICES **) PeiServices,
- (EFI_PHYSICAL_ADDRESS)(UINTN) SecCoreData->TemporaryRamBase,
- (EFI_PHYSICAL_ADDRESS)(UINTN) NewPermenentMemoryBase,
- SecCoreData->TemporaryRamSize
- );
-
- } else {
- //
- // In IA32/x64/Itanium architecture, we need platform provide
- // TEMPORAY_RAM_MIGRATION_PPI.
- //
- ASSERT (FALSE);
- }
-
-
- //
- //
- // Fixup the PeiCore's private data
- //
- PrivateInMem->Ps = &PrivateInMem->ServiceTableShadow;
- PrivateInMem->CpuIo = &PrivateInMem->ServiceTableShadow.CpuIo;
- PrivateInMem->HobList.Raw = (VOID*) ((UINTN) PrivateInMem->HobList.Raw + HeapOffset);
- PrivateInMem->StackBase = (EFI_PHYSICAL_ADDRESS)(((UINTN)PrivateInMem->PhysicalMemoryBegin + EFI_PAGE_MASK) & ~EFI_PAGE_MASK);
-
- PeiServices = (CONST EFI_PEI_SERVICES **) &PrivateInMem->Ps;
-
- //
- // Fixup for PeiService's address
- //
- SetPeiServicesTablePointer(PeiServices);
-
- //
- // Update HandOffHob for new installed permenent memory
- //
- NewHandOffTable->EfiEndOfHobList =
- (EFI_PHYSICAL_ADDRESS)((UINTN) NewHandOffTable->EfiEndOfHobList + HeapOffset);
- NewHandOffTable->EfiMemoryTop = PrivateInMem->PhysicalMemoryBegin +
- PrivateInMem->PhysicalMemoryLength;
- NewHandOffTable->EfiMemoryBottom = PrivateInMem->PhysicalMemoryBegin;
- NewHandOffTable->EfiFreeMemoryTop = PrivateInMem->FreePhysicalMemoryTop;
- NewHandOffTable->EfiFreeMemoryBottom = NewHandOffTable->EfiEndOfHobList +
- sizeof (EFI_HOB_GENERIC_HEADER);
-
- //
- // We need convert the PPI desciptor's pointer
- //
- ConvertPpiPointers (PrivateInMem,
- OldCheckingBottom,
- OldCheckingTop,
- HeapOffset
- );
-
- DEBUG ((EFI_D_INFO, "Stack Hob: BaseAddress=0x%lX Length=0x%lX\n",
- PrivateInMem->StackBase,
- PrivateInMem->StackSize));
- BuildStackHob (PrivateInMem->StackBase, PrivateInMem->StackSize);
-
- //
- // After the whole temporary memory is migrated, then we can allocate page in
- // permenent memory.
- //
- PrivateInMem->PeiMemoryInstalled = TRUE;
-
- //
- // Indicate that PeiCore reenter
- //
- PrivateInMem->PeimDispatcherReenter = TRUE;
-
- if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
- //
- // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
- // Every bit in the array indicate the status of the corresponding memory page available or not
- //
- PrivateInMem->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64));
- }
- //
- // Shadow PEI Core. When permanent memory is avaiable, shadow
- // PEI Core and PEIMs to get high performance.
- //
- PrivateInMem->ShadowedPeiCore = ShadowPeiCore (
- PeiServices,
- PrivateInMem
- );
- //
- // Process the Notify list and dispatch any notifies for
- // newly installed PPIs.
- //
- ProcessNotifyList (PrivateInMem);
-
- //
- // Entry PEI Phase 2
- //
- PeiCore (SecCoreData, NULL, PrivateInMem);
-
- //
- // Code should not come here
- //
- ASSERT_EFI_ERROR(FALSE);
- }
+ PeiCheckAndSwitchStack (SecCoreData, Private);
//
// Process the Notify list and dispatch any notifies for
// newly installed PPIs.
//
- ProcessNotifyList (Private);
+ ProcessDispatchNotifyList (Private);
- if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISITER_FOR_SHADOW) && \
- (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
+ //
+ // Recheck SwitchStackSignal after ProcessDispatchNotifyList()
+ // 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_REGISTER_FOR_SHADOW) && \
+ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
+ PcdGetBool (PcdShadowPeimOnS3Boot))
+ )
+ {
//
- // If memory is availble we shadow images by default for performance reasons.
+ // If memory is available 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);
+ // PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
+ if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) &&
+ !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes))
+ {
+ //
+ // Load PEIM into Memory for Register for shadow PEIM.
+ //
+ Status = PeiLoadImage (
+ PeiServices,
+ PeimFileHandle,
+ PEIM_STATE_REGISTER_FOR_SHADOW,
+ &EntryPoint,
+ &AuthenticationState
+ );
+ if (Status == EFI_SUCCESS) {
+ PeimEntryPoint = (EFI_PEIM_ENTRY_POINT2)(UINTN)EntryPoint;
+ }
+ }
+
ASSERT (PeimEntryPoint != NULL);
- PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **) PeiServices);
- //PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
+ PeimEntryPoint (PeimFileHandle, (const EFI_PEI_SERVICES **)PeiServices);
+ // PERF_END (PeiServices, L"PEIM", PeimFileHandle, 0);
//
- // PEIM_STATE_REGISITER_FOR_SHADOW move to PEIM_STATE_DONE
+ // PEIM_STATE_REGISTER_FOR_SHADOW move to PEIM_STATE_DONE
//
Private->Fv[FvCount].PeimState[PeimCount]++;
@@ -1004,41 +1617,36 @@ PeiDispatcher (
// Process the Notify list and dispatch any notifies for
// newly installed PPIs.
//
- ProcessNotifyList (Private);
+ ProcessDispatchNotifyList (Private);
}
}
}
}
//
- // 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, we should set them to NULL/0 to
+ // start at the beginning of the next FV.
//
- // Before walking through the next FV,Private->CurrentFvFileHandles[]should set to NULL
- //
- SetMem (Private->CurrentFvFileHandles, sizeof (Private->CurrentFvFileHandles), 0);
+ Private->CurrentFileHandle = NULL;
+ Private->CurrentPeimCount = 0;
+ Private->CurrentFvFileHandles = NULL;
}
//
- // Before making another pass, we should set Private->CurrentPeimFvCount =0 to go
- // through all the FV.
+ // Before making another pass, we should set it to 0 to
+ // go through all the FVs.
//
Private->CurrentPeimFvCount = 0;
//
- // PeimNeedingDispatch being TRUE means we found a PEIM that did not get
+ // PeimNeedingDispatch being TRUE means we found a PEIM/FV that did not get
// dispatched. So we need to make another pass
//
- // 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
+ // PeimDispatchOnThisPass being TRUE means we dispatched a PEIM/FV on this
+ // pass. If we did not dispatch a PEIM/FV there is no point in trying again
// as it will fail the next time too (nothing has changed).
//
} while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);
-
}
/**
@@ -1046,7 +1654,7 @@ PeiDispatcher (
@param PrivateData PeiCore's private data structure
@param OldCoreData Old data from SecCore
- NULL if being run in non-permament memory mode.
+ NULL if being run in non-permanent memory mode.
@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.
@@ -1056,9 +1664,9 @@ PeiDispatcher (
**/
VOID
InitializeDispatcherData (
- IN PEI_CORE_INSTANCE *PrivateData,
- IN PEI_CORE_INSTANCE *OldCoreData,
- IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN PEI_CORE_INSTANCE *OldCoreData,
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
)
{
if (OldCoreData == NULL) {
@@ -1086,18 +1694,27 @@ InitializeDispatcherData (
**/
BOOLEAN
DepexSatisfied (
- IN PEI_CORE_INSTANCE *Private,
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN UINTN PeimCount
+ IN PEI_CORE_INSTANCE *Private,
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN UINTN PeimCount
)
{
- EFI_STATUS Status;
- VOID *DepexData;
+ EFI_STATUS Status;
+ VOID *DepexData;
+ EFI_FV_FILE_INFO FileInfo;
+
+ Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(Unknown)\n"));
+ } else {
+ DEBUG ((DEBUG_DISPATCH, "Evaluate PEI DEPEX for FFS(%g)\n", &FileInfo.FileName));
+ }
if (PeimCount < Private->AprioriCount) {
//
- // If its in the A priori file then we set Depex to TRUE
+ // If it's in the Apriori file then we set DEPEX to TRUE
//
+ DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (Apriori)\n"));
return TRUE;
}
@@ -1105,15 +1722,16 @@ DepexSatisfied (
// Depex section not in the encapsulated section.
//
Status = PeiServicesFfsFindSectionData (
- EFI_SECTION_PEI_DEPEX,
- FileHandle,
- (VOID **)&DepexData
- );
+ EFI_SECTION_PEI_DEPEX,
+ FileHandle,
+ (VOID **)&DepexData
+ );
if (EFI_ERROR (Status)) {
//
// If there is no DEPEX, assume the module can be executed
//
+ DEBUG ((DEBUG_DISPATCH, " RESULT = TRUE (No DEPEX)\n"));
return TRUE;
}
@@ -1124,8 +1742,8 @@ DepexSatisfied (
}
/**
- This routine enable a PEIM to register itself to shadow when PEI Foundation
- discovery permanent memory.
+ This routine enables a PEIM to register itself for shadow when the PEI Foundation
+ discovers permanent memory.
@param FileHandle File handle of a PEIM.
@@ -1137,10 +1755,11 @@ DepexSatisfied (
EFI_STATUS
EFIAPI
PeiRegisterForShadow (
- IN EFI_PEI_FILE_HANDLE FileHandle
+ IN EFI_PEI_FILE_HANDLE FileHandle
)
{
- PEI_CORE_INSTANCE *Private;
+ PEI_CORE_INSTANCE *Private;
+
Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
if (Private->CurrentFileHandle != FileHandle) {
@@ -1150,17 +1769,14 @@ PeiRegisterForShadow (
return EFI_NOT_FOUND;
}
- if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISITER_FOR_SHADOW) {
+ if (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] >= PEIM_STATE_REGISTER_FOR_SHADOW) {
//
// If the PEIM has already entered the PEIM_STATE_REGISTER_FOR_SHADOW or PEIM_STATE_DONE then it's already been started
//
return EFI_ALREADY_STARTED;
}
- Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISITER_FOR_SHADOW;
+ Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] = PEIM_STATE_REGISTER_FOR_SHADOW;
return EFI_SUCCESS;
}
-
-
-