mirror of https://github.com/acidanthera/audk.git
Enable "Load Module At fixed Address" feature in SMM Core
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10166 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
de558d9dfe
commit
3c447c2760
|
@ -122,6 +122,176 @@ FV_FILEPATH_DEVICE_PATH mFvDevicePath;
|
||||||
//
|
//
|
||||||
EFI_SECURITY_ARCH_PROTOCOL *mSecurity = NULL;
|
EFI_SECURITY_ARCH_PROTOCOL *mSecurity = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The global variable is defined for Loading modules at fixed address feature to track the SMM 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 *mSmmCodeMemoryRangeUsageBitMap=NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
To check memory usage bit map array to figure out if the memory range in which the image will be loaded 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 SmmCodePageNumber;
|
||||||
|
UINT64 SmmCodeSize;
|
||||||
|
EFI_PHYSICAL_ADDRESS SmmCodeBase;
|
||||||
|
UINTN BaseOffsetPageNumber;
|
||||||
|
UINTN TopOffsetPageNumber;
|
||||||
|
UINTN Index;
|
||||||
|
//
|
||||||
|
// Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
|
||||||
|
//
|
||||||
|
SmmCodePageNumber = PcdGet32(PcdLoadFixAddressSmmCodePageNumber);
|
||||||
|
SmmCodeSize = EFI_PAGES_TO_SIZE (SmmCodePageNumber);
|
||||||
|
SmmCodeBase = gLoadModuleAtFixAddressSmramBase;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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 (mSmmCodeMemoryRangeUsageBitMap == NULL) {
|
||||||
|
mSmmCodeMemoryRangeUsageBitMap = AllocateZeroPool(((SmmCodePageNumber / 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 (mSmmCodeMemoryRangeUsageBitMap == NULL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// see if the memory range for loading the image is in the SMM code range.
|
||||||
|
//
|
||||||
|
if (SmmCodeBase + SmmCodeSize < ImageBase + ImageSize || SmmCodeBase > ImageBase) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Test if the memory is avalaible or not.
|
||||||
|
//
|
||||||
|
BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase - SmmCodeBase));
|
||||||
|
TopOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - SmmCodeBase));
|
||||||
|
for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {
|
||||||
|
if ((mSmmCodeMemoryRangeUsageBitMap[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 ++) {
|
||||||
|
mSmmCodeMemoryRangeUsageBitMap[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;
|
||||||
|
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);
|
||||||
|
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.So there is an assumption that when the feature is enabled,
|
||||||
|
// if a module with a loading address assigned by tools, the 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 in which uild tool saves the
|
||||||
|
// offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields
|
||||||
|
//
|
||||||
|
FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader);
|
||||||
|
//
|
||||||
|
// Check if the memory range is avaliable.
|
||||||
|
//
|
||||||
|
Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoaddingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));
|
||||||
|
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 %x, Status = %r\n", FixLoaddingAddress, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
Loads an EFI image into SMRAM.
|
Loads an EFI image into SMRAM.
|
||||||
|
|
||||||
|
@ -258,7 +428,45 @@ SmmLoadImage (
|
||||||
}
|
}
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// if Loading module at Fixed Address feature is enabled, then cut out a memory range started from TESG BASE
|
||||||
|
// to hold the Smm driver code
|
||||||
|
//
|
||||||
|
if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
//
|
||||||
|
// Get the fixed loading address assigned by Build tool
|
||||||
|
//
|
||||||
|
Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Since the memory range to load Smm core alreay been cut out, so no need to allocate and free this range
|
||||||
|
// following statements is to bypass SmmFreePages
|
||||||
|
//
|
||||||
|
PageCount = 0;
|
||||||
|
DstBuffer = (UINTN)gLoadModuleAtFixAddressSmramBase;
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));
|
||||||
|
//
|
||||||
|
// allocate the memory to load the SMM driver
|
||||||
|
//
|
||||||
|
PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
|
||||||
|
DstBuffer = (UINTN)(-1);
|
||||||
|
|
||||||
|
Status = SmmAllocatePages (
|
||||||
|
AllocateMaxAddress,
|
||||||
|
EfiRuntimeServicesCode,
|
||||||
|
PageCount,
|
||||||
|
&DstBuffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
if (Buffer != NULL) {
|
||||||
|
Status = gBS->FreePool (Buffer);
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
|
PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
|
||||||
DstBuffer = (UINTN)(-1);
|
DstBuffer = (UINTN)(-1);
|
||||||
|
|
||||||
|
@ -276,6 +484,7 @@ SmmLoadImage (
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
|
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Align buffer on section boundry
|
// Align buffer on section boundry
|
||||||
//
|
//
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <Library/DevicePathLib.h>
|
#include <Library/DevicePathLib.h>
|
||||||
#include <Library/UefiLib.h>
|
#include <Library/UefiLib.h>
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Library/PcdLib.h>
|
||||||
|
|
||||||
#include "PiSmmCorePrivateData.h"
|
#include "PiSmmCorePrivateData.h"
|
||||||
|
|
||||||
|
@ -178,6 +179,7 @@ typedef struct {
|
||||||
extern SMM_CORE_PRIVATE_DATA *gSmmCorePrivate;
|
extern SMM_CORE_PRIVATE_DATA *gSmmCorePrivate;
|
||||||
extern EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst;
|
extern EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst;
|
||||||
extern LIST_ENTRY gHandleList;
|
extern LIST_ENTRY gHandleList;
|
||||||
|
extern EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Called to initialize the memory service.
|
Called to initialize the memory service.
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
MdePkg/MdePkg.dec
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
UefiDriverEntryPoint
|
UefiDriverEntryPoint
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
UefiLib
|
UefiLib
|
||||||
UefiBootServicesTableLib
|
UefiBootServicesTableLib
|
||||||
MemoryAllocationLib
|
MemoryAllocationLib
|
||||||
|
PcdLib
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
@ -62,6 +64,10 @@
|
||||||
gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
|
gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
|
||||||
gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
|
gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber # SIMETIMES_CONSUMED
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable # ALWAYS_CONSUMED
|
||||||
|
|
||||||
[Guids]
|
[Guids]
|
||||||
gAprioriGuid # ALWAYS_CONSUMED
|
gAprioriGuid # ALWAYS_CONSUMED
|
||||||
gEfiEventDxeDispatchGuid # ALWAYS_CONSUMED
|
gEfiEventDxeDispatchGuid # ALWAYS_CONSUMED
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <Guid/EventGroup.h>
|
#include <Guid/EventGroup.h>
|
||||||
#include <Guid/EventLegacyBios.h>
|
#include <Guid/EventLegacyBios.h>
|
||||||
|
#include <Guid/LoadModuleAtFixedAddress.h>
|
||||||
|
|
||||||
#include <Library/BaseLib.h>
|
#include <Library/BaseLib.h>
|
||||||
#include <Library/BaseMemoryLib.h>
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
#include <Library/DxeServicesTableLib.h>
|
#include <Library/DxeServicesTableLib.h>
|
||||||
#include <Library/UefiLib.h>
|
#include <Library/UefiLib.h>
|
||||||
#include <Library/UefiRuntimeLib.h>
|
#include <Library/UefiRuntimeLib.h>
|
||||||
|
#include <Library/PcdLib.h>
|
||||||
|
|
||||||
#include "PiSmmCorePrivateData.h"
|
#include "PiSmmCorePrivateData.h"
|
||||||
|
|
||||||
|
@ -703,7 +705,101 @@ GetSectionInAnyFv (
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
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;
|
||||||
|
EFI_PHYSICAL_ADDRESS FixLoaddingAddress;
|
||||||
|
UINT16 Index;
|
||||||
|
UINTN Size;
|
||||||
|
UINT16 NumberOfSections;
|
||||||
|
EFI_PHYSICAL_ADDRESS SmramBase;
|
||||||
|
UINT64 SmmCodeSize;
|
||||||
|
UINT64 ValueInSectionHeader;
|
||||||
|
//
|
||||||
|
// Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
|
||||||
|
//
|
||||||
|
SmmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32(PcdLoadFixAddressSmmCodePageNumber));
|
||||||
|
|
||||||
|
FixLoaddingAddress = 0;
|
||||||
|
Status = EFI_NOT_FOUND;
|
||||||
|
SmramBase = mCurrentSmramRange->CpuStart;
|
||||||
|
//
|
||||||
|
// Get PeHeader pointer
|
||||||
|
//
|
||||||
|
ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + 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 saves the offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields in the
|
||||||
|
// first section header that doesn't point to code section in 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) {
|
||||||
|
//
|
||||||
|
// Found first section header that doesn't point to code section in which uild tool saves the
|
||||||
|
// offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields
|
||||||
|
//
|
||||||
|
FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(SmramBase + (INT64)ValueInSectionHeader);
|
||||||
|
|
||||||
|
if (SmramBase + SmmCodeSize > FixLoaddingAddress && SmramBase <= FixLoaddingAddress) {
|
||||||
|
//
|
||||||
|
// The assigned address is valid. Return the specified loadding address
|
||||||
|
//
|
||||||
|
ImageContext->ImageAddress = FixLoaddingAddress;
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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", FixLoaddingAddress, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM.
|
Load the SMM Core image into SMRAM and executes the SMM Core from SMRAM.
|
||||||
|
|
||||||
|
@ -749,7 +845,22 @@ ExecuteSmmCoreFromSmram (
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// if Loading module at Fixed Address feature is enabled, the SMM core driver will be loaded to
|
||||||
|
// the address assigned by build tool.
|
||||||
|
//
|
||||||
|
if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
//
|
||||||
|
// Get the fixed loading address assigned by Build tool
|
||||||
|
//
|
||||||
|
Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// Since the memory range to load SMM CORE will be cut out in SMM core, so no need to allocate and free this range
|
||||||
|
//
|
||||||
|
PageCount = 0;
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED ERROR: Loading module at fixed address at address failed\n"));
|
||||||
//
|
//
|
||||||
// Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
|
// Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
|
||||||
// specified by SmramRange
|
// specified by SmramRange
|
||||||
|
@ -766,6 +877,26 @@ ExecuteSmmCoreFromSmram (
|
||||||
// Align buffer on section boundry
|
// Align buffer on section boundry
|
||||||
//
|
//
|
||||||
ImageContext.ImageAddress = DestinationBuffer;
|
ImageContext.ImageAddress = DestinationBuffer;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR
|
||||||
|
// specified by SmramRange
|
||||||
|
//
|
||||||
|
PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);
|
||||||
|
|
||||||
|
ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);
|
||||||
|
ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));
|
||||||
|
|
||||||
|
SmramRange->PhysicalSize -= EFI_PAGES_TO_SIZE (PageCount);
|
||||||
|
DestinationBuffer = SmramRange->CpuStart + SmramRange->PhysicalSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Align buffer on section boundry
|
||||||
|
//
|
||||||
|
ImageContext.ImageAddress = DestinationBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
|
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
|
||||||
ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
|
ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
|
||||||
|
|
||||||
|
@ -847,6 +978,8 @@ SmmIplEntry (
|
||||||
EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion;
|
EFI_SMM_RESERVED_SMRAM_REGION *SmramResRegion;
|
||||||
UINT64 MaxSize;
|
UINT64 MaxSize;
|
||||||
VOID *Registration;
|
VOID *Registration;
|
||||||
|
UINT64 SmmCodeSize;
|
||||||
|
EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE *LMFAConfigurationTable;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fill in the image handle of the SMM IPL so the SMM Core can use this as the
|
// Fill in the image handle of the SMM IPL so the SMM Core can use this as the
|
||||||
|
@ -954,7 +1087,34 @@ SmmIplEntry (
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n"));
|
DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n"));
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// if Loading module at Fixed Address feature is enabled, save the SMRAM base to Load
|
||||||
|
// Modules At Fixed Address Configuration Table.
|
||||||
|
//
|
||||||
|
if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
//
|
||||||
|
// Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
|
||||||
|
//
|
||||||
|
SmmCodeSize = LShiftU64 (PcdGet32(PcdLoadFixAddressSmmCodePageNumber), EFI_PAGE_SHIFT);
|
||||||
|
//
|
||||||
|
// The SMRAM available memory is assumed to be larger than SmmCodeSize
|
||||||
|
//
|
||||||
|
ASSERT (mCurrentSmramRange->PhysicalSize > SmmCodeSize);
|
||||||
|
//
|
||||||
|
// Retrieve Load modules At fixed address configuration table and save the SMRAM base.
|
||||||
|
//
|
||||||
|
Status = EfiGetSystemConfigurationTable (
|
||||||
|
&gLoadFixedAddressConfigurationTableGuid,
|
||||||
|
(VOID **) &LMFAConfigurationTable
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status) && LMFAConfigurationTable != NULL) {
|
||||||
|
LMFAConfigurationTable->SmramBase = mCurrentSmramRange->CpuStart;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Print the SMRAM base
|
||||||
|
//
|
||||||
|
DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: TSEG BASE is %x. \n", LMFAConfigurationTable->SmramBase));
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Load SMM Core into SMRAM and execute it from SMRAM
|
// Load SMM Core into SMRAM and execute it from SMRAM
|
||||||
//
|
//
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
MdePkg/MdePkg.dec
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
UefiDriverEntryPoint
|
UefiDriverEntryPoint
|
||||||
|
@ -62,6 +63,12 @@
|
||||||
gEfiEventReadyToBootGuid # ALWAYS_CONSUMED
|
gEfiEventReadyToBootGuid # ALWAYS_CONSUMED
|
||||||
gEfiEventLegacyBootGuid # ALWAYS_CONSUMED
|
gEfiEventLegacyBootGuid # ALWAYS_CONSUMED
|
||||||
gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED
|
gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED
|
||||||
|
gLoadFixedAddressConfigurationTableGuid # SIMETIMES_CONSUMED
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber # SIMETIMES_CONSUMED
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable # ALWAYS_CONSUMED
|
||||||
|
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid AND gEfiCpuArchProtocolGuid
|
gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid AND gEfiCpuArchProtocolGuid
|
||||||
|
|
|
@ -42,6 +42,11 @@ typedef struct {
|
||||||
} FREE_POOL_HEADER;
|
} FREE_POOL_HEADER;
|
||||||
|
|
||||||
LIST_ENTRY mSmmPoolLists[MAX_POOL_INDEX];
|
LIST_ENTRY mSmmPoolLists[MAX_POOL_INDEX];
|
||||||
|
//
|
||||||
|
// To cache the SMRAM base since when Loading modules At fixed address feature is enabled,
|
||||||
|
// all module is assigned an offset relative the SMRAM base in build time.
|
||||||
|
//
|
||||||
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PHYSICAL_ADDRESS gLoadModuleAtFixAddressSmramBase = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Called to initialize the memory service.
|
Called to initialize the memory service.
|
||||||
|
@ -57,6 +62,9 @@ SmmInitializeMemoryServices (
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
|
UINT64 SmmCodeSize;
|
||||||
|
UINTN CurrentSmramRangesIndex;
|
||||||
|
UINT64 MaxSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Initialize Pool list
|
// Initialize Pool list
|
||||||
|
@ -64,7 +72,38 @@ SmmInitializeMemoryServices (
|
||||||
for (Index = sizeof (mSmmPoolLists) / sizeof (*mSmmPoolLists); Index > 0;) {
|
for (Index = sizeof (mSmmPoolLists) / sizeof (*mSmmPoolLists); Index > 0;) {
|
||||||
InitializeListHead (&mSmmPoolLists[--Index]);
|
InitializeListHead (&mSmmPoolLists[--Index]);
|
||||||
}
|
}
|
||||||
|
CurrentSmramRangesIndex = 0;
|
||||||
|
//
|
||||||
|
// If Loadding Module At fixed Address feature is enabled, cache the SMRAM base here
|
||||||
|
//
|
||||||
|
if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
|
||||||
|
//
|
||||||
|
// Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber
|
||||||
|
//
|
||||||
|
SmmCodeSize = LShiftU64 (PcdGet32(PcdLoadFixAddressSmmCodePageNumber), EFI_PAGE_SHIFT);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find the largest SMRAM range between 1MB and 4GB that is at least 256KB - 4K in size
|
||||||
|
//
|
||||||
|
for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < SmramRangeCount; Index++) {
|
||||||
|
if (SmramRanges[Index].CpuStart >= BASE_1MB) {
|
||||||
|
if ((SmramRanges[Index].CpuStart + SmramRanges[Index].PhysicalSize) <= BASE_4GB) {
|
||||||
|
if (SmramRanges[Index].PhysicalSize >= MaxSize) {
|
||||||
|
MaxSize = SmramRanges[Index].PhysicalSize;
|
||||||
|
CurrentSmramRangesIndex = Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gLoadModuleAtFixAddressSmramBase = SmramRanges[CurrentSmramRangesIndex].CpuStart;
|
||||||
|
|
||||||
|
//
|
||||||
|
// cut out a memory range from this SMRAM range with the size SmmCodeSize to hold SMM driver code
|
||||||
|
// A notable thing is that SMM core is already loaded into this range.
|
||||||
|
//
|
||||||
|
SmramRanges[CurrentSmramRangesIndex].CpuStart = SmramRanges[CurrentSmramRangesIndex].CpuStart + SmmCodeSize;
|
||||||
|
SmramRanges[CurrentSmramRangesIndex].PhysicalSize = SmramRanges[CurrentSmramRangesIndex].PhysicalSize - SmmCodeSize;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Initialize free SMRAM regions
|
// Initialize free SMRAM regions
|
||||||
//
|
//
|
||||||
|
@ -76,6 +115,7 @@ SmmInitializeMemoryServices (
|
||||||
SmramRanges[Index].RegionState
|
SmramRanges[Index].RegionState
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -28,7 +28,7 @@ extern EFI_GUID gLoadFixedAddressConfigurationTableGuid;
|
||||||
|
|
||||||
typedef struct {
|
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 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_PHYSICAL_ADDRESS SmramBase; ///< SMM RAME base. build tool will assigned an offset relative to SMRAM base for SMM driver
|
||||||
} EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE;
|
} EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue