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:
rsun3 2010-03-17 02:06:04 +00:00
parent 49fd8a3553
commit 673c149801
4 changed files with 69 additions and 127 deletions

View File

@ -77,6 +77,7 @@ typedef struct {
SMMBASE_FUNCTION Function; SMMBASE_FUNCTION Function;
EFI_STATUS Status; EFI_STATUS Status;
SMMBASE_FUNCTION_ARGS Args; SMMBASE_FUNCTION_ARGS Args;
EFI_HANDLE SmmBaseImageHandle;
} SMMBASE_FUNCTION_DATA; } SMMBASE_FUNCTION_DATA;
#pragma pack(1) #pragma pack(1)

View File

@ -31,6 +31,7 @@
#include <Protocol/LoadedImage.h> #include <Protocol/LoadedImage.h>
#include <Protocol/SmmCpuSaveState.h> #include <Protocol/SmmCpuSaveState.h>
#include <Protocol/MpService.h> #include <Protocol/MpService.h>
#include <Protocol/LoadPe32Image.h>
/// ///
/// Structure for tracking paired information of registered Framework SMI handler /// Structure for tracking paired information of registered Framework SMI handler
@ -59,6 +60,7 @@ typedef struct {
EFI_HANDLE mDispatchHandle; EFI_HANDLE mDispatchHandle;
EFI_SMM_CPU_PROTOCOL *mSmmCpu; EFI_SMM_CPU_PROTOCOL *mSmmCpu;
EFI_PE32_IMAGE_PROTOCOL *mLoadPe32Image;
EFI_GUID mEfiSmmCpuIoGuid = EFI_SMM_CPU_IO_GUID; EFI_GUID mEfiSmmCpuIoGuid = EFI_SMM_CPU_IO_GUID;
EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady; EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady;
EFI_SMM_SYSTEM_TABLE *mFrameworkSmst; EFI_SMM_SYSTEM_TABLE *mFrameworkSmst;
@ -174,6 +176,7 @@ ConstructFrameworkSmst (
/** /**
Load a given Framework SMM driver into SMRAM and invoke its entry point. 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] FilePath Location of the image to be installed as the handler.
@param[in] SourceBuffer Optional source buffer in case the image file @param[in] SourceBuffer Optional source buffer in case the image file
is in memory. is in memory.
@ -189,6 +192,7 @@ ConstructFrameworkSmst (
**/ **/
EFI_STATUS EFI_STATUS
LoadImage ( LoadImage (
IN EFI_HANDLE ParentImageHandle,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN VOID *SourceBuffer, IN VOID *SourceBuffer,
IN UINTN SourceSize, IN UINTN SourceSize,
@ -197,141 +201,63 @@ LoadImage (
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINTN PageCount; UINTN PageCount;
EFI_PHYSICAL_ADDRESS Buffer; UINTN OrgPageCount;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; EFI_PHYSICAL_ADDRESS DstBuffer;
EFI_HANDLE PesudoImageHandle;
UINTN NumHandles;
UINTN Index;
EFI_HANDLE *HandleBuffer;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
EFI_DEVICE_PATH *LoadedImageDevicePath;
UINTN DevicePathSize;
if (FilePath == NULL || ImageHandle == NULL) { if (FilePath == NULL || ImageHandle == NULL) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
/// PageCount = 1;
/// Assume Framework SMM driver has an image copy in memory before registering itself into SMRAM. do {
/// Currently only supports load Framework SMM driver from existing image copy in memory. OrgPageCount = PageCount;
/// Load PE32 Image Protocol can be used to support loading Framework SMM driver directly from FV. DstBuffer = (UINTN)-1;
/// Status = gSmst->SmmAllocatePages (
if (SourceBuffer == NULL) { AllocateMaxAddress,
Status = gBS->LocateHandleBuffer ( EfiRuntimeServicesCode,
ByProtocol, PageCount,
&gEfiLoadedImageDevicePathProtocolGuid, &DstBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = mLoadPe32Image->LoadPeImage (
mLoadPe32Image,
ParentImageHandle,
FilePath,
SourceBuffer,
SourceSize,
DstBuffer,
&PageCount,
ImageHandle,
NULL, NULL,
&NumHandles, EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE
&HandleBuffer
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED; FreePages ((VOID *)(UINTN)DstBuffer, OrgPageCount);
} }
} while (Status == EFI_BUFFER_TOO_SMALL);
DevicePathSize = GetDevicePathSize (FilePath); if (!EFI_ERROR (Status)) {
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);
/// ///
/// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point
/// in case it may invoke AP /// in case it may invoke AP
/// ///
mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu; mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;
/// Status = gBS->StartImage (*ImageHandle, NULL, NULL);
/// For Framework SMM, ImageHandle does not have to be a UEFI image handle. The only requirement is that the if (EFI_ERROR (Status)) {
/// ImageHandle is a unique value. Use image base address as the unique value. mLoadPe32Image->UnLoadPeImage (mLoadPe32Image, *ImageHandle);
/// *ImageHandle = NULL;
PesudoImageHandle = (EFI_HANDLE)(UINTN)ImageContext.ImageAddress; FreePages ((VOID *)(UINTN)DstBuffer, PageCount);
}
Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)ImageContext.EntryPoint) (PesudoImageHandle, gST);
if (!EFI_ERROR (Status)) {
*ImageHandle = PesudoImageHandle;
return EFI_SUCCESS;
} }
Error: return Status;
FreePages ((VOID *)(UINTN)Buffer, PageCount);
return EFI_SUCCESS;
} }
/** /**
Thunk service of EFI_SMM_BASE_PROTOCOL.Register(). Thunk service of EFI_SMM_BASE_PROTOCOL.Register().
@ -348,6 +274,7 @@ Register (
Status = EFI_UNSUPPORTED; Status = EFI_UNSUPPORTED;
} else { } else {
Status = LoadImage ( Status = LoadImage (
FunctionData->SmmBaseImageHandle,
FunctionData->Args.Register.FilePath, FunctionData->Args.Register.FilePath,
FunctionData->Args.Register.SourceBuffer, FunctionData->Args.Register.SourceBuffer,
FunctionData->Args.Register.SourceSize, FunctionData->Args.Register.SourceSize,
@ -735,6 +662,12 @@ SmmBaseHelperMain (
Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu); Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);
ASSERT_EFI_ERROR (Status); 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 // Get MP Services Protocol
// //

View File

@ -33,6 +33,7 @@
[Packages] [Packages]
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec IntelFrameworkPkg/IntelFrameworkPkg.dec
EdkCompatibilityPkg/EdkCompatibilityPkg.dec EdkCompatibilityPkg/EdkCompatibilityPkg.dec
@ -57,6 +58,10 @@
gEfiSmmCpuSaveStateProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiSmmCpuSaveStateProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSmmCpuIo2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiSmmCpuIo2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLoadPeImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
[Depex] [Depex]
gEfiSmmCpuProtocolGuid AND gEfiMpServiceProtocolGuid AND gEfiSmmCpuIo2ProtocolGuid gEfiSmmCpuProtocolGuid AND
gEfiMpServiceProtocolGuid AND
gEfiSmmCpuIo2ProtocolGuid AND
gEfiLoadPeImageProtocolGuid

View File

@ -75,6 +75,7 @@ SmmBaseHelperService (
UINTN DataSize; UINTN DataSize;
mCommunicationData.FunctionData.Status = EFI_UNSUPPORTED; mCommunicationData.FunctionData.Status = EFI_UNSUPPORTED;
mCommunicationData.FunctionData.SmmBaseImageHandle = mSmmBaseHandle;
if ((mCommunicationData.FunctionData.Function != SmmBaseFunctionCommunicate) && IsInSmm()) { if ((mCommunicationData.FunctionData.Function != SmmBaseFunctionCommunicate) && IsInSmm()) {
/// ///
@ -421,6 +422,8 @@ SmmBaseThunkMain (
EFI_STATUS Status; EFI_STATUS Status;
EFI_EVENT Event; EFI_EVENT Event;
mSmmBaseHandle = ImageHandle;
// //
// Assume only one instance of SMM Base2 Protocol in the system // Assume only one instance of SMM Base2 Protocol in the system
// Locate SMM Base2 Protocol // Locate SMM Base2 Protocol