mirror of https://github.com/acidanthera/audk.git
Enable the Load Module At fixed Address feature
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9937 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
f3198cba84
commit
54ea99a798
|
@ -60,7 +60,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#include <Guid/MemoryAllocationHob.h>
|
#include <Guid/MemoryAllocationHob.h>
|
||||||
#include <Guid/EventLegacyBios.h>
|
#include <Guid/EventLegacyBios.h>
|
||||||
#include <Guid/EventGroup.h>
|
#include <Guid/EventGroup.h>
|
||||||
|
#include <Guid/LoadModuleAtFixedAddress.h>
|
||||||
|
|
||||||
#include <Library/DxeCoreEntryPoint.h>
|
#include <Library/DxeCoreEntryPoint.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
|
@ -81,6 +81,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
#include <Library/TimerLib.h>
|
#include <Library/TimerLib.h>
|
||||||
#include <Library/DxeServicesLib.h>
|
#include <Library/DxeServicesLib.h>
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// attributes for reserved memory before it is promoted to system memory
|
// attributes for reserved memory before it is promoted to system memory
|
||||||
//
|
//
|
||||||
|
@ -204,6 +205,8 @@ extern EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMem
|
||||||
extern BOOLEAN gDispatcherRunning;
|
extern BOOLEAN gDispatcherRunning;
|
||||||
extern EFI_RUNTIME_ARCH_PROTOCOL gRuntimeTemplate;
|
extern EFI_RUNTIME_ARCH_PROTOCOL gRuntimeTemplate;
|
||||||
|
|
||||||
|
extern EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE gLoadModuleAtFixAddressConfigurationTable;
|
||||||
|
extern BOOLEAN gLoadFixedAddressCodeMemoryReady;
|
||||||
//
|
//
|
||||||
// Service Initialization Functions
|
// Service Initialization Functions
|
||||||
//
|
//
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
gEfiDxeServicesTableGuid ## CONSUMES ## GUID
|
gEfiDxeServicesTableGuid ## CONSUMES ## GUID
|
||||||
gEfiMemoryTypeInformationGuid ## CONSUMES ## GUID
|
gEfiMemoryTypeInformationGuid ## CONSUMES ## GUID
|
||||||
gEfiEventDxeDispatchGuid ## CONSUMES ## GUID
|
gEfiEventDxeDispatchGuid ## CONSUMES ## GUID
|
||||||
|
gLoadFixedAddressConfigurationTableGuid ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
|
@ -138,3 +139,10 @@
|
||||||
|
|
||||||
[FeaturePcd.common]
|
[FeaturePcd.common]
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES
|
||||||
|
|
||||||
|
[FixedPcd.common]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable ## CONSUMES
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber ## SOMETIMES_CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber ## SOMETIMES_CONSUMES
|
|
@ -210,6 +210,11 @@ EFI_DECOMPRESS_PROTOCOL gEfiDecompress = {
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
// For Loading modules at fixed address feature, the configuration table is to cache the top address below which to load
|
||||||
|
// Runtime code&boot time code
|
||||||
|
//
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE gLoadModuleAtFixAddressConfigurationTable;
|
||||||
|
|
||||||
// Main entry point to the DXE Core
|
// Main entry point to the DXE Core
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -284,7 +289,16 @@ DxeMain (
|
||||||
//
|
//
|
||||||
Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation);
|
Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation);
|
||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// If Loading modules At fixed address feature is enabled, install Load moduels at fixed address
|
||||||
|
// Configuration Table so that user could easily to retrieve the top address to load Dxe and PEI
|
||||||
|
// Code and Tseg base to load SMM driver.
|
||||||
|
//
|
||||||
|
if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
Status = CoreInstallConfigurationTable (&gLoadFixedAddressConfigurationTableGuid, &gLoadModuleAtFixAddressConfigurationTable);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Report Status Code here for DXE_ENTRY_POINT once it is available
|
// Report Status Code here for DXE_ENTRY_POINT once it is available
|
||||||
//
|
//
|
||||||
|
|
|
@ -1765,6 +1765,7 @@ CoreInitializeMemoryServices (
|
||||||
EFI_PHYSICAL_ADDRESS HighAddress;
|
EFI_PHYSICAL_ADDRESS HighAddress;
|
||||||
EFI_HOB_RESOURCE_DESCRIPTOR *MaxResourceHob;
|
EFI_HOB_RESOURCE_DESCRIPTOR *MaxResourceHob;
|
||||||
EFI_HOB_GUID_TYPE *GuidHob;
|
EFI_HOB_GUID_TYPE *GuidHob;
|
||||||
|
UINT32 ReservedCodePageNumber;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Point at the first HOB. This must be the PHIT HOB.
|
// Point at the first HOB. This must be the PHIT HOB.
|
||||||
|
@ -1795,7 +1796,17 @@ CoreInitializeMemoryServices (
|
||||||
// Cache the PHIT HOB for later use
|
// Cache the PHIT HOB for later use
|
||||||
//
|
//
|
||||||
PhitHob = Hob.HandoffInformationTable;
|
PhitHob = Hob.HandoffInformationTable;
|
||||||
|
|
||||||
|
if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
ReservedCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);
|
||||||
|
ReservedCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);
|
||||||
|
|
||||||
|
//
|
||||||
|
// cache the Top address for loading modules at Fixed Address
|
||||||
|
//
|
||||||
|
gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress = PhitHob->EfiMemoryTop
|
||||||
|
+ EFI_PAGES_TO_SIZE(ReservedCodePageNumber);
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// See if a Memory Type Information HOB is available
|
// See if a Memory Type Information HOB is available
|
||||||
//
|
//
|
||||||
|
|
|
@ -70,8 +70,12 @@ LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = {
|
||||||
NULL, // RuntimeData
|
NULL, // RuntimeData
|
||||||
NULL // LoadedImageDevicePath
|
NULL // LoadedImageDevicePath
|
||||||
};
|
};
|
||||||
|
//
|
||||||
|
// The field is define for Loading modules at fixed address feature to tracker the PEI code
|
||||||
|
// memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page
|
||||||
|
// available or not.
|
||||||
|
//
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mDxeCodeMemoryRangeUsageBitMap=NULL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Add the Image Services to EFI Boot Services Table and install the protocol
|
Add the Image Services to EFI Boot Services Table and install the protocol
|
||||||
|
@ -202,7 +206,170 @@ CoreReadImageFile (
|
||||||
CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);
|
CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
To check memory usage bit map arry to figure out if the memory range the image will be loaded in is available or not. If
|
||||||
|
memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used.
|
||||||
|
The function is only invoked when load modules at fixed address feature is enabled.
|
||||||
|
|
||||||
|
@param ImageBase The base addres the image will be loaded at.
|
||||||
|
@param ImageSize The size of the image
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The memory range the image will be loaded in is available
|
||||||
|
@retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
CheckAndMarkFixLoadingMemoryUsageBitMap (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS ImageBase,
|
||||||
|
IN UINTN ImageSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 DxeCodePageNumber;
|
||||||
|
UINT64 DxeCodeSize;
|
||||||
|
EFI_PHYSICAL_ADDRESS DxeCodeBase;
|
||||||
|
UINTN BaseOffsetPageNumber;
|
||||||
|
UINTN TopOffsetPageNumber;
|
||||||
|
UINTN Index;
|
||||||
|
//
|
||||||
|
// The DXE code range includes RuntimeCodePage range and Boot time code range.
|
||||||
|
//
|
||||||
|
DxeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);
|
||||||
|
DxeCodePageNumber += PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);
|
||||||
|
DxeCodeSize = EFI_PAGES_TO_SIZE(DxeCodePageNumber);
|
||||||
|
DxeCodeBase = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - DxeCodeSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the memory usage bit map is not initialized, do it. Every bit in the array
|
||||||
|
// indicate the status of the corresponding memory page, available or not
|
||||||
|
//
|
||||||
|
if (mDxeCodeMemoryRangeUsageBitMap == NULL) {
|
||||||
|
mDxeCodeMemoryRangeUsageBitMap = AllocateZeroPool(((DxeCodePageNumber/64) + 1)*sizeof(UINT64));
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND
|
||||||
|
//
|
||||||
|
if (!gLoadFixedAddressCodeMemoryReady || mDxeCodeMemoryRangeUsageBitMap == NULL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Test the memory range for loading the image in the DXE code range.
|
||||||
|
//
|
||||||
|
if (gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress < ImageBase + ImageSize ||
|
||||||
|
DxeCodeBase > ImageBase) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Test if the memory is avalaible or not.
|
||||||
|
//
|
||||||
|
BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase - DxeCodeBase));
|
||||||
|
TopOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - DxeCodeBase));
|
||||||
|
for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
|
||||||
|
if ((mDxeCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {
|
||||||
|
//
|
||||||
|
// This page is already used.
|
||||||
|
//
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Being here means the memory range is available. So mark the bits for the memory range
|
||||||
|
//
|
||||||
|
for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
|
||||||
|
mDxeCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));
|
||||||
|
}
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
|
||||||
|
Get the fixed loadding address from image header assigned by build tool. This function only be called
|
||||||
|
when Loading module at Fixed address feature enabled.
|
||||||
|
|
||||||
|
@param ImageContext Pointer to the image context structure that describes the PE/COFF
|
||||||
|
image that needs to be examined by this function.
|
||||||
|
@retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
|
||||||
|
@retval EFI_NOT_FOUND The image has no assigned fixed loadding address.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetPeCoffImageFixLoadingAssignedAddress(
|
||||||
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN SectionHeaderOffset;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_IMAGE_SECTION_HEADER SectionHeader;
|
||||||
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
|
||||||
|
UINT16 Index;
|
||||||
|
UINTN Size;
|
||||||
|
UINT16 NumberOfSections;
|
||||||
|
IMAGE_FILE_HANDLE *Handle;
|
||||||
|
UINT64 ValueInSectionHeader;
|
||||||
|
|
||||||
|
|
||||||
|
Status = EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get PeHeader pointer
|
||||||
|
//
|
||||||
|
Handle = (IMAGE_FILE_HANDLE*)ImageContext->Handle;
|
||||||
|
ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )Handle->Source + ImageContext->PeCoffHeaderOffset);
|
||||||
|
SectionHeaderOffset = (UINTN)(
|
||||||
|
ImageContext->PeCoffHeaderOffset +
|
||||||
|
sizeof (UINT32) +
|
||||||
|
sizeof (EFI_IMAGE_FILE_HEADER) +
|
||||||
|
ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
|
||||||
|
);
|
||||||
|
NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get base address from the first section header that doesn't point to code section.
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < NumberOfSections; Index++) {
|
||||||
|
//
|
||||||
|
// Read section header from file
|
||||||
|
//
|
||||||
|
Size = sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||||
|
Status = ImageContext->ImageRead (
|
||||||
|
ImageContext->Handle,
|
||||||
|
SectionHeaderOffset,
|
||||||
|
&Size,
|
||||||
|
&SectionHeader
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
|
||||||
|
//
|
||||||
|
// Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
|
||||||
|
// that doesn't point to code section in image header, as well as ImageBase field of image header. And there is an
|
||||||
|
// assumption that when the feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations
|
||||||
|
// & PointerToLineNumbers fields should NOT be Zero, or else, these 2 fileds should be set to Zero
|
||||||
|
//
|
||||||
|
ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);
|
||||||
|
if (ValueInSectionHeader != 0) {
|
||||||
|
//
|
||||||
|
// When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
|
||||||
|
// hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
|
||||||
|
// relative to top address
|
||||||
|
//
|
||||||
|
if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {
|
||||||
|
ImageContext->ImageAddress = gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress + (INT64)ImageContext->ImageAddress;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Check if the memory range is avaliable.
|
||||||
|
//
|
||||||
|
Status = CheckAndMarkFixLoadingMemoryUsageBitMap (ImageContext->ImageAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||||
|
}
|
||||||
|
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x. Status = %r \n", ImageContext->ImageAddress, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
Loads, relocates, and invokes a PE/COFF image
|
Loads, relocates, and invokes a PE/COFF image
|
||||||
|
|
||||||
|
@ -308,21 +475,43 @@ CoreLoadPeImage (
|
||||||
// no modules whose preferred load addresses are below 1MB.
|
// no modules whose preferred load addresses are below 1MB.
|
||||||
//
|
//
|
||||||
Status = EFI_OUT_OF_RESOURCES;
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {
|
//
|
||||||
Status = CoreAllocatePages (
|
// If Loading Module At Fixed Address feature is enabled, the module should be loaded to
|
||||||
AllocateAddress,
|
// a specified address.
|
||||||
(EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
|
//
|
||||||
Image->NumberOfPages,
|
if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 ) {
|
||||||
&Image->ImageContext.ImageAddress
|
Status = GetPeCoffImageFixLoadingAssignedAddress (&(Image->ImageContext));
|
||||||
);
|
|
||||||
}
|
if (EFI_ERROR (Status)) {
|
||||||
if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {
|
//
|
||||||
Status = CoreAllocatePages (
|
// If the code memory is not ready, invoke CoreAllocatePage with AllocateAnyPages to load the driver.
|
||||||
AllocateAnyPages,
|
//
|
||||||
(EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
|
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Loading module at fixed address failed since specified memory is not available.\n"));
|
||||||
Image->NumberOfPages,
|
|
||||||
&Image->ImageContext.ImageAddress
|
Status = CoreAllocatePages (
|
||||||
);
|
AllocateAnyPages,
|
||||||
|
(EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
|
||||||
|
Image->NumberOfPages,
|
||||||
|
&Image->ImageContext.ImageAddress
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {
|
||||||
|
Status = CoreAllocatePages (
|
||||||
|
AllocateAddress,
|
||||||
|
(EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
|
||||||
|
Image->NumberOfPages,
|
||||||
|
&Image->ImageContext.ImageAddress
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {
|
||||||
|
Status = CoreAllocatePages (
|
||||||
|
AllocateAnyPages,
|
||||||
|
(EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),
|
||||||
|
Image->NumberOfPages,
|
||||||
|
&Image->ImageContext.ImageAddress
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -355,9 +544,9 @@ CoreLoadPeImage (
|
||||||
|
|
||||||
Image->ImageBasePage = Image->ImageContext.ImageAddress;
|
Image->ImageBasePage = Image->ImageContext.ImageAddress;
|
||||||
if (!Image->ImageContext.IsTeImage) {
|
if (!Image->ImageContext.IsTeImage) {
|
||||||
Image->ImageContext.ImageAddress =
|
Image->ImageContext.ImageAddress =
|
||||||
(Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
|
(Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &
|
||||||
~((UINTN)Image->ImageContext.SectionAlignment - 1);
|
~((UINTN)Image->ImageContext.SectionAlignment - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -89,7 +89,12 @@ EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
|
||||||
{ EfiPalCode, 0 },
|
{ EfiPalCode, 0 },
|
||||||
{ EfiMaxMemoryType, 0 }
|
{ EfiMaxMemoryType, 0 }
|
||||||
};
|
};
|
||||||
|
//
|
||||||
|
// Only used when load module at fixed address feature is enabled. True means the memory is alreay successfully allocated
|
||||||
|
// and ready to load the module in to specified address.or else, the memory is not ready and module will be loaded at a
|
||||||
|
// address assigned by DXE core.
|
||||||
|
//
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN gLoadFixedAddressCodeMemoryReady = FALSE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enter critical section by gaining lock on gMemoryLock.
|
Enter critical section by gaining lock on gMemoryLock.
|
||||||
|
@ -419,7 +424,70 @@ PromoteMemoryResource (
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
This function try to allocate Runtime code & Boot time code memory range. If LMFA enabled, 2 patchable PCD
|
||||||
|
PcdLoadFixAddressRuntimeCodePageNumber & PcdLoadFixAddressBootTimeCodePageNumber which are set by tools will record the
|
||||||
|
size of boot time and runtime code.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
CoreLoadingFixedAddressHook (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 RuntimeCodePageNumber;
|
||||||
|
UINT32 BootTimeCodePageNumber;
|
||||||
|
EFI_PHYSICAL_ADDRESS RuntimeCodeBase;
|
||||||
|
EFI_PHYSICAL_ADDRESS BootTimeCodeBase;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make sure these 2 areas are not initialzied.
|
||||||
|
//
|
||||||
|
if (!gLoadFixedAddressCodeMemoryReady) {
|
||||||
|
RuntimeCodePageNumber = PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);
|
||||||
|
BootTimeCodePageNumber= PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);
|
||||||
|
RuntimeCodeBase = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressConfigurationTable.DxeCodeTopAddress - EFI_PAGES_TO_SIZE (RuntimeCodePageNumber));
|
||||||
|
BootTimeCodeBase = (EFI_PHYSICAL_ADDRESS)(RuntimeCodeBase - EFI_PAGES_TO_SIZE (BootTimeCodePageNumber));
|
||||||
|
//
|
||||||
|
// Try to allocate runtime memory.
|
||||||
|
//
|
||||||
|
Status = CoreAllocatePages (
|
||||||
|
AllocateAddress,
|
||||||
|
EfiRuntimeServicesCode,
|
||||||
|
RuntimeCodePageNumber,
|
||||||
|
&RuntimeCodeBase
|
||||||
|
);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
//
|
||||||
|
// Runtime memory allocation failed
|
||||||
|
//
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Try to allocate boot memory.
|
||||||
|
//
|
||||||
|
Status = CoreAllocatePages (
|
||||||
|
AllocateAddress,
|
||||||
|
EfiBootServicesCode,
|
||||||
|
BootTimeCodePageNumber,
|
||||||
|
&BootTimeCodeBase
|
||||||
|
);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
//
|
||||||
|
// boot memory allocation failed. Free Runtime code range and will try the allocation again when
|
||||||
|
// new memory range is installed.
|
||||||
|
//
|
||||||
|
CoreFreePages (
|
||||||
|
RuntimeCodeBase,
|
||||||
|
RuntimeCodePageNumber
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gLoadFixedAddressCodeMemoryReady = TRUE;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Called to initialize the memory map and add descriptors to
|
Called to initialize the memory map and add descriptors to
|
||||||
|
@ -448,7 +516,7 @@ CoreAddMemoryDescriptor (
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
UINTN FreeIndex;
|
UINTN FreeIndex;
|
||||||
|
|
||||||
if ((Start & EFI_PAGE_MASK) != 0) {
|
if ((Start & EFI_PAGE_MASK) != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -456,13 +524,19 @@ CoreAddMemoryDescriptor (
|
||||||
if (Type >= EfiMaxMemoryType && Type <= 0x7fffffff) {
|
if (Type >= EfiMaxMemoryType && Type <= 0x7fffffff) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreAcquireMemoryLock ();
|
CoreAcquireMemoryLock ();
|
||||||
End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;
|
End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1;
|
||||||
CoreAddRange (Type, Start, End, Attribute);
|
CoreAddRange (Type, Start, End, Attribute);
|
||||||
CoreFreeMemoryMapStack ();
|
CoreFreeMemoryMapStack ();
|
||||||
CoreReleaseMemoryLock ();
|
CoreReleaseMemoryLock ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// If Loading Module At Fixed Address feature is enabled. try to allocate memory with Runtime code & Boot time code type
|
||||||
|
//
|
||||||
|
if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
CoreLoadingFixedAddressHook();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check to see if the statistics for the different memory types have already been established
|
// Check to see if the statistics for the different memory types have already been established
|
||||||
//
|
//
|
||||||
|
@ -470,6 +544,7 @@ CoreAddMemoryDescriptor (
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
|
// Loop through each memory type in the order specified by the gMemoryTypeInformation[] array
|
||||||
//
|
//
|
||||||
|
@ -481,7 +556,6 @@ CoreAddMemoryDescriptor (
|
||||||
if (Type < 0 || Type > EfiMaxMemoryType) {
|
if (Type < 0 || Type > EfiMaxMemoryType) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
|
if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
|
||||||
//
|
//
|
||||||
// Allocate pages for the current memory type from the top of available memory
|
// Allocate pages for the current memory type from the top of available memory
|
||||||
|
@ -549,7 +623,6 @@ CoreAddMemoryDescriptor (
|
||||||
if (Type < 0 || Type > EfiMaxMemoryType) {
|
if (Type < 0 || Type > EfiMaxMemoryType) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
|
if (gMemoryTypeInformation[Index].NumberOfPages != 0) {
|
||||||
CoreFreePages (
|
CoreFreePages (
|
||||||
mMemoryTypeStatistics[Type].BaseAddress,
|
mMemoryTypeStatistics[Type].BaseAddress,
|
||||||
|
|
|
@ -233,7 +233,326 @@ ShadowPeiCore(
|
||||||
//
|
//
|
||||||
return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);
|
return (VOID*) ((UINTN) EntryPoint + (UINTN) PeiCore - (UINTN) _ModuleEntryPoint);
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
@param PrivateData Pointer to the private data passed in from caller
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
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;
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
//
|
||||||
|
// 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 = EFI_PAGES_TO_SIZE(PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)+ PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber))
|
||||||
|
+ MINIMUM_INITIAL_MEMORY_SIZE;
|
||||||
|
|
||||||
|
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressRuntimeCodePageNumber= %x.\n", PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber)));
|
||||||
|
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressBootTimeCodePageNumber= %x.\n", PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber)));
|
||||||
|
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PcdLoadFixAddressPeiCodePageNumber= %x.\n", PcdGet32(PcdLoadFixAddressPeiCodePageNumber)));
|
||||||
|
//
|
||||||
|
// PEI memory range lies below the top reserved memory
|
||||||
|
//
|
||||||
|
TotalReservedMemorySize += PeiMemorySize;
|
||||||
|
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: Total Reserved Memory Size = %lx.\n", TotalReservedMemorySize));
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
|
||||||
|
|
||||||
|
ResourceHob = Hob.ResourceDescriptor;
|
||||||
|
//
|
||||||
|
// If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.
|
||||||
|
//
|
||||||
|
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){
|
||||||
|
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)){
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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);
|
||||||
|
//
|
||||||
|
// Delete the NextResourceHob by marking it as unused.
|
||||||
|
//
|
||||||
|
GET_HOB_TYPE (NextHob) = EFI_HOB_TYPE_UNUSED;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Try to find and validate the TOP address.
|
||||||
|
//
|
||||||
|
if ((INT64)FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) > 0 ) {
|
||||||
|
//
|
||||||
|
// The LMFA feature is enabled as load module at fixed absolute address.
|
||||||
|
//
|
||||||
|
TopLoadingAddress = (EFI_PHYSICAL_ADDRESS)FixedPcdGet64(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 %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 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 %lx is valid \n", TopLoadingAddress));
|
||||||
|
TopLoadingAddress += MINIMUM_INITIAL_MEMORY_SIZE;
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR:Top Address %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, "(%lx, %lx)\n",
|
||||||
|
(ResourceHob->PhysicalStart + TotalReservedMemorySize -MINIMUM_INITIAL_MEMORY_SIZE),
|
||||||
|
(ResourceHob->PhysicalStart + ResourceHob->ResourceLength -MINIMUM_INITIAL_MEMORY_SIZE)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Assert here
|
||||||
|
//
|
||||||
|
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)) {
|
||||||
|
//
|
||||||
|
// 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 &&
|
||||||
|
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"));
|
||||||
|
//
|
||||||
|
// Assert here
|
||||||
|
//
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// 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 = %lx\n", PrivateData->LoadModuleAtFixAddressTopAddress));
|
||||||
|
//
|
||||||
|
// reinstall the PEI memory relative to TopLoadingAddress
|
||||||
|
//
|
||||||
|
PrivateData->PhysicalMemoryBegin = TopLoadingAddress - TotalReservedMemorySize;
|
||||||
|
PrivateData->FreePhysicalMemoryTop = PrivateData->PhysicalMemoryBegin + PeiMemorySize;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
Conduct PEIM dispatch.
|
Conduct PEIM dispatch.
|
||||||
|
|
||||||
|
@ -277,6 +596,7 @@ PeiDispatcher (
|
||||||
UINTN OldCheckingTop;
|
UINTN OldCheckingTop;
|
||||||
UINTN OldCheckingBottom;
|
UINTN OldCheckingBottom;
|
||||||
PEI_CORE_FV_HANDLE *CoreFvHandle;
|
PEI_CORE_FV_HANDLE *CoreFvHandle;
|
||||||
|
VOID *LoadFixPeiCodeBegin;
|
||||||
|
|
||||||
PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;
|
PeiServices = (CONST EFI_PEI_SERVICES **) &Private->PS;
|
||||||
PeimEntryPoint = NULL;
|
PeimEntryPoint = NULL;
|
||||||
|
@ -476,6 +796,13 @@ PeiDispatcher (
|
||||||
));
|
));
|
||||||
DEBUG_CODE_END ();
|
DEBUG_CODE_END ();
|
||||||
|
|
||||||
|
if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
//
|
||||||
|
// Loading Module at Fixed Address is enabled
|
||||||
|
//
|
||||||
|
PeiLoadFixAddressHook(Private);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reserve the size of new stack at bottom of physical memory
|
// Reserve the size of new stack at bottom of physical memory
|
||||||
//
|
//
|
||||||
|
@ -613,6 +940,19 @@ PeiDispatcher (
|
||||||
//
|
//
|
||||||
PrivateInMem->PeimDispatcherReenter = TRUE;
|
PrivateInMem->PeimDispatcherReenter = TRUE;
|
||||||
|
|
||||||
|
if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
//
|
||||||
|
// if Loading Module at Fixed Address is enabled, This is the first invoke to page
|
||||||
|
// allocation for Pei Core segment. This memory segment should be reserved for loading PEIM
|
||||||
|
//
|
||||||
|
LoadFixPeiCodeBegin = AllocatePages((UINTN)PcdGet32(PcdLoadFixAddressPeiCodePageNumber));
|
||||||
|
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: PeiCodeBegin = %x, PeiCodeTop= %x\n", (UINTN)LoadFixPeiCodeBegin, ((UINTN)LoadFixPeiCodeBegin) + PcdGet32(PcdLoadFixAddressPeiCodePageNumber) * EFI_PAGE_SIZE));
|
||||||
|
//
|
||||||
|
// 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
|
// Shadow PEI Core. When permanent memory is avaiable, shadow
|
||||||
// PEI Core and PEIMs to get high performance.
|
// PEI Core and PEIMs to get high performance.
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
/** @file
|
/** @file
|
||||||
Pei Core Load Image Support
|
Pei Core Load Image Support
|
||||||
|
|
||||||
Copyright (c) 2006 - 2010, Intel Corporation
|
Copyright (c) 2006 - 2010, Intel Corporation
|
||||||
All rights reserved. This program and the accompanying materials
|
All rights reserved. This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
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
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
http://opensource.org/licenses/bsd-license.php
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
@ -96,7 +96,192 @@ GetImageReadFunction (
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
To check memory usage bit map arry to figure out if the memory range the image will be loaded in is available or not. If
|
||||||
|
memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used.
|
||||||
|
The function is only invoked when load modules at fixed address feature is enabled.
|
||||||
|
|
||||||
|
@param Private Pointer to the private data passed in from caller
|
||||||
|
@param ImageBase The base addres the image will be loaded at.
|
||||||
|
@param ImageSize The size of the image
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The memory range the image will be loaded in is available
|
||||||
|
@retval EFI_NOT_FOUND The memory range the image will be loaded in is not available
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
CheckAndMarkFixLoadingMemoryUsageBitMap (
|
||||||
|
IN PEI_CORE_INSTANCE *Private,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS ImageBase,
|
||||||
|
IN UINT32 ImageSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 DxeCodePageNumber;
|
||||||
|
UINT64 ReservedCodeSize;
|
||||||
|
EFI_PHYSICAL_ADDRESS PeiCodeBase;
|
||||||
|
UINT32 BaseOffsetPageNumber;
|
||||||
|
UINT32 TopOffsetPageNumber;
|
||||||
|
UINT32 Index;
|
||||||
|
UINT64 *MemoryUsageBitMap;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// The reserved code range includes RuntimeCodePage range, Boot time code range and PEI code range.
|
||||||
|
//
|
||||||
|
DxeCodePageNumber = PcdGet32(PcdLoadFixAddressBootTimeCodePageNumber);
|
||||||
|
DxeCodePageNumber += PcdGet32(PcdLoadFixAddressRuntimeCodePageNumber);
|
||||||
|
ReservedCodeSize = EFI_PAGES_TO_SIZE(DxeCodePageNumber + PcdGet32(PcdLoadFixAddressPeiCodePageNumber));
|
||||||
|
PeiCodeBase = Private->LoadModuleAtFixAddressTopAddress - ReservedCodeSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test the memory range for loading the image in the PEI code range.
|
||||||
|
//
|
||||||
|
if ((Private->LoadModuleAtFixAddressTopAddress - EFI_PAGES_TO_SIZE(DxeCodePageNumber)) < (ImageBase + ImageSize) ||
|
||||||
|
(PeiCodeBase > ImageBase)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test if the memory is avalaible or not.
|
||||||
|
//
|
||||||
|
MemoryUsageBitMap = Private->PeiCodeMemoryRangeUsageBitMap;
|
||||||
|
BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - PeiCodeBase));
|
||||||
|
TopOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - PeiCodeBase));
|
||||||
|
for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
|
||||||
|
if ((MemoryUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {
|
||||||
|
//
|
||||||
|
// This page is already used.
|
||||||
|
//
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Being here means the memory range is available. So mark the bits for the memory range
|
||||||
|
//
|
||||||
|
for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
|
||||||
|
MemoryUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));
|
||||||
|
}
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
|
||||||
|
Get the fixed loadding address from image header assigned by build tool. This function only be called
|
||||||
|
when Loading module at Fixed address feature enabled.
|
||||||
|
|
||||||
|
@param ImageContext Pointer to the image context structure that describes the PE/COFF
|
||||||
|
image that needs to be examined by this function.
|
||||||
|
@param Private Pointer to the private data passed in from caller
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .
|
||||||
|
@retval EFI_NOT_FOUND The image has no assigned fixed loadding address.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetPeCoffImageFixLoadingAssignedAddress(
|
||||||
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
||||||
|
IN PEI_CORE_INSTANCE *Private
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN SectionHeaderOffset;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_IMAGE_SECTION_HEADER SectionHeader;
|
||||||
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
|
||||||
|
EFI_PHYSICAL_ADDRESS FixLoaddingAddress;
|
||||||
|
UINT16 Index;
|
||||||
|
UINTN Size;
|
||||||
|
UINT16 NumberOfSections;
|
||||||
|
UINT64 ValueInSectionHeader;
|
||||||
|
|
||||||
|
|
||||||
|
FixLoaddingAddress = 0;
|
||||||
|
Status = EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get PeHeader pointer
|
||||||
|
//
|
||||||
|
ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
|
||||||
|
if (ImageContext->IsTeImage) {
|
||||||
|
//
|
||||||
|
// for TE image, the fix loadding address is saved in first section header that doesn't point
|
||||||
|
// to code section.
|
||||||
|
//
|
||||||
|
SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER);
|
||||||
|
NumberOfSections = ImgHdr->Te.NumberOfSections;
|
||||||
|
} else {
|
||||||
|
SectionHeaderOffset = (UINTN)(
|
||||||
|
ImageContext->PeCoffHeaderOffset +
|
||||||
|
sizeof (UINT32) +
|
||||||
|
sizeof (EFI_IMAGE_FILE_HEADER) +
|
||||||
|
ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
|
||||||
|
);
|
||||||
|
NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Get base address from the first section header that doesn't point to code section.
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < NumberOfSections; Index++) {
|
||||||
|
//
|
||||||
|
// Read section header from file
|
||||||
|
//
|
||||||
|
Size = sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||||
|
Status = ImageContext->ImageRead (
|
||||||
|
ImageContext->Handle,
|
||||||
|
SectionHeaderOffset,
|
||||||
|
&Size,
|
||||||
|
&SectionHeader
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
|
||||||
|
//
|
||||||
|
// Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header
|
||||||
|
// that doesn't point to code section in image header, as well as ImageBase field of image header. A notable thing is
|
||||||
|
// that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because
|
||||||
|
// for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers
|
||||||
|
// hold the image base address when it is shadow to the memory. And there is an assumption that when the feature is enabled, if a
|
||||||
|
// module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or
|
||||||
|
// else, these 2 fileds should be set to Zero
|
||||||
|
//
|
||||||
|
ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);
|
||||||
|
if (ValueInSectionHeader != 0) {
|
||||||
|
//
|
||||||
|
// Found first section header that doesn't point to code section.
|
||||||
|
//
|
||||||
|
if ((INT64)FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) > 0) {
|
||||||
|
//
|
||||||
|
// When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field
|
||||||
|
// hold the absolute address of image base runing in memory
|
||||||
|
//
|
||||||
|
FixLoaddingAddress = ValueInSectionHeader;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field
|
||||||
|
// hold the offset relative to a platform-specific top address.
|
||||||
|
//
|
||||||
|
FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + (INT64)ValueInSectionHeader);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Check if the memory range is avaliable.
|
||||||
|
//
|
||||||
|
Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoaddingAddress, (UINT32) ImageContext->ImageSize);
|
||||||
|
if (!EFI_ERROR(Status)) {
|
||||||
|
//
|
||||||
|
// The assigned address is valid. Return the specified loadding address
|
||||||
|
//
|
||||||
|
ImageContext->ImageAddress = FixLoaddingAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
|
||||||
|
}
|
||||||
|
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %lx. Status= %r \n", FixLoaddingAddress, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Loads and relocates a PE/COFF image into memory.
|
Loads and relocates a PE/COFF image into memory.
|
||||||
|
@ -139,29 +324,40 @@ LoadAndRelocatePeCoffImage (
|
||||||
// When Image has no reloc section, it can't be relocated into memory.
|
// When Image has no reloc section, it can't be relocated into memory.
|
||||||
//
|
//
|
||||||
if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
|
if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
|
||||||
DEBUG ((EFI_D_INFO, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));
|
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set default base address to current image address.
|
// Set default base address to current image address.
|
||||||
//
|
//
|
||||||
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data;
|
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate Memory for the image when memory is ready, boot mode is not S3, and image is relocatable.
|
// Allocate Memory for the image when memory is ready, boot mode is not S3, and image is relocatable.
|
||||||
//
|
//
|
||||||
if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
|
if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
|
||||||
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
|
if (FixedPcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
Status = GetPeCoffImageFixLoadingAssignedAddress(&ImageContext, Private);
|
||||||
|
if (EFI_ERROR (Status)){
|
||||||
|
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
|
||||||
|
//
|
||||||
|
// The PEIM is not assiged valid address, try to allocate page to load it.
|
||||||
|
//
|
||||||
|
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
|
||||||
|
}
|
||||||
ASSERT (ImageContext.ImageAddress != 0);
|
ASSERT (ImageContext.ImageAddress != 0);
|
||||||
if (ImageContext.ImageAddress == 0) {
|
if (ImageContext.ImageAddress == 0) {
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Skip the reserved space for the stripped PeHeader when load TeImage into memory.
|
// Skip the reserved space for the stripped PeHeader when load TeImage into memory.
|
||||||
//
|
//
|
||||||
if (ImageContext.IsTeImage) {
|
if (ImageContext.IsTeImage) {
|
||||||
ImageContext.ImageAddress = ImageContext.ImageAddress +
|
ImageContext.ImageAddress = ImageContext.ImageAddress +
|
||||||
((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -
|
((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -
|
||||||
sizeof (EFI_TE_IMAGE_HEADER);
|
sizeof (EFI_TE_IMAGE_HEADER);
|
||||||
}
|
}
|
||||||
|
@ -197,8 +393,8 @@ LoadAndRelocatePeCoffImage (
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Loads a PEIM into memory for subsequent execution. If there are compressed
|
Loads a PEIM into memory for subsequent execution. If there are compressed
|
||||||
images or images that need to be relocated into memory for performance reasons,
|
images or images that need to be relocated into memory for performance reasons,
|
||||||
this service performs that transformation.
|
this service performs that transformation.
|
||||||
|
|
||||||
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
|
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
|
||||||
|
@ -245,7 +441,7 @@ PeiLoadImageLoadImage (
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
|
// Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
|
||||||
// is true, TE will be searched first).
|
// is true, TE will be searched first).
|
||||||
//
|
//
|
||||||
Status = PeiServicesFfsFindSectionData (
|
Status = PeiServicesFfsFindSectionData (
|
||||||
|
@ -270,7 +466,7 @@ PeiLoadImageLoadImage (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// If memory is installed, perform the shadow operations
|
// If memory is installed, perform the shadow operations
|
||||||
//
|
//
|
||||||
|
@ -293,9 +489,9 @@ PeiLoadImageLoadImage (
|
||||||
//
|
//
|
||||||
Pe32Data = (VOID *) ((UINTN) ImageAddress);
|
Pe32Data = (VOID *) ((UINTN) ImageAddress);
|
||||||
*EntryPoint = ImageEntryPoint;
|
*EntryPoint = ImageEntryPoint;
|
||||||
|
|
||||||
Machine = PeCoffLoaderGetMachineType (Pe32Data);
|
Machine = PeCoffLoaderGetMachineType (Pe32Data);
|
||||||
|
|
||||||
if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {
|
if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {
|
||||||
if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {
|
if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
|
@ -309,7 +505,7 @@ PeiLoadImageLoadImage (
|
||||||
if (ImageSizeArg != NULL) {
|
if (ImageSizeArg != NULL) {
|
||||||
*ImageSizeArg = ImageSize;
|
*ImageSizeArg = ImageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_CODE_BEGIN ();
|
DEBUG_CODE_BEGIN ();
|
||||||
CHAR8 *AsciiString;
|
CHAR8 *AsciiString;
|
||||||
CHAR8 AsciiBuffer[512];
|
CHAR8 AsciiBuffer[512];
|
||||||
|
@ -327,12 +523,12 @@ PeiLoadImageLoadImage (
|
||||||
//
|
//
|
||||||
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));
|
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Print Module Name by PeImage PDB file name.
|
// Print Module Name by PeImage PDB file name.
|
||||||
//
|
//
|
||||||
AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);
|
AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);
|
||||||
|
|
||||||
if (AsciiString != NULL) {
|
if (AsciiString != NULL) {
|
||||||
for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {
|
for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {
|
||||||
if (AsciiString[Index] == '\\') {
|
if (AsciiString[Index] == '\\') {
|
||||||
|
@ -454,7 +650,7 @@ RelocationIsStrip (
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Routine to load image file for subsequent execution by LoadFile Ppi.
|
Routine to load image file for subsequent execution by LoadFile Ppi.
|
||||||
If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE
|
If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE
|
||||||
XIP image format is used.
|
XIP image format is used.
|
||||||
|
|
||||||
@param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
|
@param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
|
||||||
|
@ -500,9 +696,9 @@ PeiLoadImage (
|
||||||
);
|
);
|
||||||
if (!EFI_ERROR (PpiStatus)) {
|
if (!EFI_ERROR (PpiStatus)) {
|
||||||
Status = LoadFile->LoadFile (
|
Status = LoadFile->LoadFile (
|
||||||
LoadFile,
|
LoadFile,
|
||||||
FileHandle,
|
FileHandle,
|
||||||
&ImageAddress,
|
&ImageAddress,
|
||||||
&ImageSize,
|
&ImageSize,
|
||||||
EntryPoint,
|
EntryPoint,
|
||||||
AuthenticationState
|
AuthenticationState
|
||||||
|
@ -560,10 +756,10 @@ InitializeImageServices (
|
||||||
PeiServicesInstallPpi (PrivateData->XipLoadFile);
|
PeiServicesInstallPpi (PrivateData->XipLoadFile);
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// 2nd time we are running from memory so replace the XIP version with the
|
// 2nd time we are running from memory so replace the XIP version with the
|
||||||
// new memory version.
|
// new memory version.
|
||||||
//
|
//
|
||||||
PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);
|
PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,18 @@ typedef struct{
|
||||||
EFI_PHYSICAL_ADDRESS FreePhysicalMemoryTop;
|
EFI_PHYSICAL_ADDRESS FreePhysicalMemoryTop;
|
||||||
VOID* ShadowedPeiCore;
|
VOID* ShadowedPeiCore;
|
||||||
CACHE_SECTION_DATA CacheSection;
|
CACHE_SECTION_DATA CacheSection;
|
||||||
|
//
|
||||||
|
// For Loading modules at fixed address feature to cache the top address below which the
|
||||||
|
// Runtime code, boot time code and PEI memory will be placed. Please note that the offset between this field
|
||||||
|
// and PS should not be changed since maybe user could get this top address by using the offet to PS.
|
||||||
|
//
|
||||||
|
EFI_PHYSICAL_ADDRESS LoadModuleAtFixAddressTopAddress;
|
||||||
|
//
|
||||||
|
// The field is define for Loading modules at fixed address feature to tracker the PEI code
|
||||||
|
// memory range usage. It is a bit mapped array in which every bit indicates the correspoding memory page
|
||||||
|
// available or not.
|
||||||
|
//
|
||||||
|
UINT64 *PeiCodeMemoryRangeUsageBitMap;
|
||||||
} PEI_CORE_INSTANCE;
|
} PEI_CORE_INSTANCE;
|
||||||
|
|
||||||
///
|
///
|
||||||
|
|
|
@ -85,12 +85,16 @@
|
||||||
gEfiTemporaryRamSupportPpiGuid ## CONSUMES
|
gEfiTemporaryRamSupportPpiGuid ## CONSUMES
|
||||||
|
|
||||||
[FixedPcd]
|
[FixedPcd]
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxFvSupported ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxFvSupported ## CONSUMES
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeimPerFv ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeimPerFv ## CONSUMES
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPpiSupported ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPpiSupported ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable ## CONSUMES
|
||||||
|
|
||||||
[Pcd]
|
[Pcd]
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize ## CONSUMES
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreImageLoaderSearchTeSectionFirst ## CONSUMES
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressPeiCodePageNumber ## SOMETIMES_CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber ## SOMETIMES_CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/** @file
|
||||||
|
This file defines:
|
||||||
|
A configuration Table Guid for Load module at fixed address.
|
||||||
|
This configuration table is to hold the top address below which the Dxe runtime code and
|
||||||
|
boot time code will be loaded and Tseg base. When this feature is enabled, Build tools will assigned
|
||||||
|
module loading address relative to these 2 address.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (c) 2010, Intel Corporation. <BR>
|
||||||
|
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.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __LOAD_MODULE_AT_FIX_ADDRESS_GUID_H__
|
||||||
|
#define __LOAD_MODULE_AT_FIX_ADDRESS_GUID_H__
|
||||||
|
|
||||||
|
#define EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE_GUID \
|
||||||
|
{ 0x2CA88B53,0xD296,0x4080, { 0xA4,0xA5,0xCA,0xD9,0xBA,0xE2,0x4B,0x9} }
|
||||||
|
|
||||||
|
|
||||||
|
extern EFI_GUID gLoadFixedAddressConfigurationTableGuid;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_PHYSICAL_ADDRESS DxeCodeTopAddress; ///< The top address below which the Dxe runtime code and below which the Dxe runtime/boot code and PEI code.
|
||||||
|
EFI_PHYSICAL_ADDRESS TsegBase; ///< Tseg base. build tool will assigned an offset relative to Tseg base to SMM driver
|
||||||
|
} EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE;
|
||||||
|
|
||||||
|
#endif
|
|
@ -143,6 +143,10 @@
|
||||||
# Include/Guid/StatusCodeDataTypeDebug.h
|
# Include/Guid/StatusCodeDataTypeDebug.h
|
||||||
gEfiStatusCodeDataTypeDebugGuid = { 0x9A4E9246, 0xD553, 0x11D5, { 0x87, 0xE2, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9 }}
|
gEfiStatusCodeDataTypeDebugGuid = { 0x9A4E9246, 0xD553, 0x11D5, { 0x87, 0xE2, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9 }}
|
||||||
|
|
||||||
|
## A configuration Table Guid for Load module at fixed address
|
||||||
|
# Include/Guid/LoadModuleAtFixedAddress.h
|
||||||
|
gLoadFixedAddressConfigurationTableGuid = { 0x2CA88B53,0xD296,0x4080, { 0xA4,0xA5,0xCA,0xD9,0xBA,0xE2,0x4B,0x9 } }
|
||||||
|
|
||||||
[Protocols.common]
|
[Protocols.common]
|
||||||
## Load File protocol provides capability to load and unload EFI image into memory and execute it.
|
## Load File protocol provides capability to load and unload EFI image into memory and execute it.
|
||||||
# Include/Protocol/LoadPe32Image.h
|
# Include/Protocol/LoadPe32Image.h
|
||||||
|
@ -343,6 +347,12 @@
|
||||||
# BIT1 set indicates 8KB alignment
|
# BIT1 set indicates 8KB alignment
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1|UINT32|0x10000047
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1|UINT32|0x10000047
|
||||||
|
|
||||||
|
## Flag of enabling/disabling the feature of Loading Module at Fixed Address
|
||||||
|
# -1: Enable the feature as fixed offset to TOLM
|
||||||
|
# 0: Disable the feature.
|
||||||
|
# Positive Value: Enable the feature as fixed absolute address, and the value is the top memory address
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable|0|UINT64|0x30001015
|
||||||
|
|
||||||
## Smbios version
|
## Smbios version
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0206|UINT16|0x00010055
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0206|UINT16|0x00010055
|
||||||
|
|
||||||
|
@ -409,3 +419,20 @@
|
||||||
# The default value in DxePhase is 128 KBytes.
|
# The default value in DxePhase is 128 KBytes.
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1|UINT16|0x00010054
|
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1|UINT16|0x00010054
|
||||||
|
|
||||||
|
[PcdsPatchableInModule]
|
||||||
|
## Specify memory size with page number for PEI code when
|
||||||
|
# the feature of Loading Module at Fixed Address is enabled
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressPeiCodePageNumber|0|UINT32|0x00000029
|
||||||
|
|
||||||
|
## Specify memory size with page number for DXE boot time code when
|
||||||
|
# the feature of Loading Module at Fixed Address is enabled
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber|0|UINT32|0x0000002a
|
||||||
|
|
||||||
|
## Specify memory size with page number for DXE runtime code when
|
||||||
|
# the feature of Loading Module at Fixed Address is enabled
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressRuntimeCodePageNumber|0|UINT32|0x0000002b
|
||||||
|
|
||||||
|
## Specify memory size with page number for SMM code when
|
||||||
|
# the feature of Loading Module at Fixed Address is enabled
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber|0|UINT32|0x0000002c
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue