mirror of https://github.com/acidanthera/audk.git
Remove the implementation limitation in the SmmBaseHelper driver that it assumes the Framework SMM driver to be loaded has a copy in memory.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10258 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
49fd8a3553
commit
673c149801
|
@ -77,6 +77,7 @@ typedef struct {
|
|||
SMMBASE_FUNCTION Function;
|
||||
EFI_STATUS Status;
|
||||
SMMBASE_FUNCTION_ARGS Args;
|
||||
EFI_HANDLE SmmBaseImageHandle;
|
||||
} SMMBASE_FUNCTION_DATA;
|
||||
|
||||
#pragma pack(1)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <Protocol/LoadedImage.h>
|
||||
#include <Protocol/SmmCpuSaveState.h>
|
||||
#include <Protocol/MpService.h>
|
||||
#include <Protocol/LoadPe32Image.h>
|
||||
|
||||
///
|
||||
/// Structure for tracking paired information of registered Framework SMI handler
|
||||
|
@ -59,6 +60,7 @@ typedef struct {
|
|||
|
||||
EFI_HANDLE mDispatchHandle;
|
||||
EFI_SMM_CPU_PROTOCOL *mSmmCpu;
|
||||
EFI_PE32_IMAGE_PROTOCOL *mLoadPe32Image;
|
||||
EFI_GUID mEfiSmmCpuIoGuid = EFI_SMM_CPU_IO_GUID;
|
||||
EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady;
|
||||
EFI_SMM_SYSTEM_TABLE *mFrameworkSmst;
|
||||
|
@ -174,6 +176,7 @@ ConstructFrameworkSmst (
|
|||
/**
|
||||
Load a given Framework SMM driver into SMRAM and invoke its entry point.
|
||||
|
||||
@param[in] ParentImageHandle Parent Image Handle.
|
||||
@param[in] FilePath Location of the image to be installed as the handler.
|
||||
@param[in] SourceBuffer Optional source buffer in case the image file
|
||||
is in memory.
|
||||
|
@ -189,6 +192,7 @@ ConstructFrameworkSmst (
|
|||
**/
|
||||
EFI_STATUS
|
||||
LoadImage (
|
||||
IN EFI_HANDLE ParentImageHandle,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||
IN VOID *SourceBuffer,
|
||||
IN UINTN SourceSize,
|
||||
|
@ -197,141 +201,63 @@ LoadImage (
|
|||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN PageCount;
|
||||
EFI_PHYSICAL_ADDRESS Buffer;
|
||||
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
|
||||
EFI_HANDLE PesudoImageHandle;
|
||||
UINTN NumHandles;
|
||||
UINTN Index;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
|
||||
EFI_DEVICE_PATH *LoadedImageDevicePath;
|
||||
UINTN DevicePathSize;
|
||||
UINTN OrgPageCount;
|
||||
EFI_PHYSICAL_ADDRESS DstBuffer;
|
||||
|
||||
if (FilePath == NULL || ImageHandle == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
///
|
||||
/// Assume Framework SMM driver has an image copy in memory before registering itself into SMRAM.
|
||||
/// Currently only supports load Framework SMM driver from existing image copy in memory.
|
||||
/// Load PE32 Image Protocol can be used to support loading Framework SMM driver directly from FV.
|
||||
///
|
||||
if (SourceBuffer == NULL) {
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
&gEfiLoadedImageDevicePathProtocolGuid,
|
||||
PageCount = 1;
|
||||
do {
|
||||
OrgPageCount = PageCount;
|
||||
DstBuffer = (UINTN)-1;
|
||||
Status = gSmst->SmmAllocatePages (
|
||||
AllocateMaxAddress,
|
||||
EfiRuntimeServicesCode,
|
||||
PageCount,
|
||||
&DstBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = mLoadPe32Image->LoadPeImage (
|
||||
mLoadPe32Image,
|
||||
ParentImageHandle,
|
||||
FilePath,
|
||||
SourceBuffer,
|
||||
SourceSize,
|
||||
DstBuffer,
|
||||
&PageCount,
|
||||
ImageHandle,
|
||||
NULL,
|
||||
&NumHandles,
|
||||
&HandleBuffer
|
||||
EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
FreePages ((VOID *)(UINTN)DstBuffer, OrgPageCount);
|
||||
}
|
||||
} while (Status == EFI_BUFFER_TOO_SMALL);
|
||||
|
||||
DevicePathSize = GetDevicePathSize (FilePath);
|
||||
|
||||
for (Index = 0; Index < NumHandles; Index++) {
|
||||
Status = gBS->HandleProtocol (
|
||||
HandleBuffer[Index],
|
||||
&gEfiLoadedImageDevicePathProtocolGuid,
|
||||
(VOID **)&LoadedImageDevicePath
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
if (GetDevicePathSize (LoadedImageDevicePath) == DevicePathSize &&
|
||||
CompareMem (LoadedImageDevicePath, FilePath, DevicePathSize) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Index < NumHandles) {
|
||||
Status = gBS->HandleProtocol (
|
||||
HandleBuffer[Index],
|
||||
&gEfiLoadedImageProtocolGuid,
|
||||
(VOID **)&LoadedImage
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
SourceBuffer = LoadedImage->ImageBase;
|
||||
gBS->FreePool (HandleBuffer);
|
||||
} else {
|
||||
gBS->FreePool (HandleBuffer);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
ImageContext.Handle = SourceBuffer;
|
||||
ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
|
||||
|
||||
///
|
||||
/// Get information about the image being loaded
|
||||
///
|
||||
Status = PeCoffLoaderGetImageInfo (&ImageContext);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
///
|
||||
/// Allocate buffer for loading image into SMRAM
|
||||
///
|
||||
PageCount = (UINTN)EFI_SIZE_TO_PAGES (ImageContext.ImageSize + ImageContext.SectionAlignment);
|
||||
Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, PageCount, &Buffer);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
ImageContext.ImageAddress = (PHYSICAL_ADDRESS)Buffer;
|
||||
|
||||
///
|
||||
/// Align buffer on section boundry
|
||||
///
|
||||
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
|
||||
ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
|
||||
|
||||
///
|
||||
/// Load the image into SMRAM
|
||||
///
|
||||
Status = PeCoffLoaderLoadImage (&ImageContext);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
///
|
||||
/// Relocate the image in our new buffer
|
||||
///
|
||||
Status = PeCoffLoaderRelocateImage (&ImageContext);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
///
|
||||
/// Flush the instruction cache so the image data are written before we execute it
|
||||
///
|
||||
InvalidateInstructionCacheRange ((VOID *)(UINTN) ImageContext.ImageAddress, (UINTN) ImageContext.ImageSize);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
///
|
||||
/// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point
|
||||
/// in case it may invoke AP
|
||||
///
|
||||
mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;
|
||||
|
||||
///
|
||||
/// For Framework SMM, ImageHandle does not have to be a UEFI image handle. The only requirement is that the
|
||||
/// ImageHandle is a unique value. Use image base address as the unique value.
|
||||
///
|
||||
PesudoImageHandle = (EFI_HANDLE)(UINTN)ImageContext.ImageAddress;
|
||||
|
||||
Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)ImageContext.EntryPoint) (PesudoImageHandle, gST);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*ImageHandle = PesudoImageHandle;
|
||||
return EFI_SUCCESS;
|
||||
Status = gBS->StartImage (*ImageHandle, NULL, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
mLoadPe32Image->UnLoadPeImage (mLoadPe32Image, *ImageHandle);
|
||||
*ImageHandle = NULL;
|
||||
FreePages ((VOID *)(UINTN)DstBuffer, PageCount);
|
||||
}
|
||||
}
|
||||
|
||||
Error:
|
||||
FreePages ((VOID *)(UINTN)Buffer, PageCount);
|
||||
return EFI_SUCCESS;
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Thunk service of EFI_SMM_BASE_PROTOCOL.Register().
|
||||
|
||||
|
@ -348,6 +274,7 @@ Register (
|
|||
Status = EFI_UNSUPPORTED;
|
||||
} else {
|
||||
Status = LoadImage (
|
||||
FunctionData->SmmBaseImageHandle,
|
||||
FunctionData->Args.Register.FilePath,
|
||||
FunctionData->Args.Register.SourceBuffer,
|
||||
FunctionData->Args.Register.SourceSize,
|
||||
|
@ -735,6 +662,12 @@ SmmBaseHelperMain (
|
|||
Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
///
|
||||
/// Locate PE32 Image Protocol which is used later to load Framework SMM driver
|
||||
///
|
||||
Status = SystemTable->BootServices->LocateProtocol (&gEfiLoadPeImageProtocolGuid, NULL, (VOID **) &mLoadPe32Image);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Get MP Services Protocol
|
||||
//
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
IntelFrameworkPkg/IntelFrameworkPkg.dec
|
||||
EdkCompatibilityPkg/EdkCompatibilityPkg.dec
|
||||
|
||||
|
@ -57,6 +58,10 @@
|
|||
gEfiSmmCpuSaveStateProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiSmmCpuIo2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiLoadPeImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
||||
[Depex]
|
||||
gEfiSmmCpuProtocolGuid AND gEfiMpServiceProtocolGuid AND gEfiSmmCpuIo2ProtocolGuid
|
||||
gEfiSmmCpuProtocolGuid AND
|
||||
gEfiMpServiceProtocolGuid AND
|
||||
gEfiSmmCpuIo2ProtocolGuid AND
|
||||
gEfiLoadPeImageProtocolGuid
|
|
@ -75,6 +75,7 @@ SmmBaseHelperService (
|
|||
UINTN DataSize;
|
||||
|
||||
mCommunicationData.FunctionData.Status = EFI_UNSUPPORTED;
|
||||
mCommunicationData.FunctionData.SmmBaseImageHandle = mSmmBaseHandle;
|
||||
|
||||
if ((mCommunicationData.FunctionData.Function != SmmBaseFunctionCommunicate) && IsInSmm()) {
|
||||
///
|
||||
|
@ -421,6 +422,8 @@ SmmBaseThunkMain (
|
|||
EFI_STATUS Status;
|
||||
EFI_EVENT Event;
|
||||
|
||||
mSmmBaseHandle = ImageHandle;
|
||||
|
||||
//
|
||||
// Assume only one instance of SMM Base2 Protocol in the system
|
||||
// Locate SMM Base2 Protocol
|
||||
|
|
Loading…
Reference in New Issue