Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StandaloneMmPkg: Call PeCoffLoaderUnloadImage When Unloading Image #10586

Merged
merged 2 commits into from
Jan 9, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 42 additions & 29 deletions StandaloneMmPkg/Core/Dispatcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,40 +101,45 @@ BOOLEAN gRequestDispatch = FALSE;
Loads an EFI image into SMRAM.

@param DriverEntry EFI_MM_DRIVER_ENTRY instance
@param ImageContext Allocated ImageContext to be filled out by this function

@return EFI_STATUS

**/
EFI_STATUS
EFIAPI
MmLoadImage (
IN OUT EFI_MM_DRIVER_ENTRY *DriverEntry
IN OUT EFI_MM_DRIVER_ENTRY *DriverEntry,
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
os-d marked this conversation as resolved.
Show resolved Hide resolved
)
{
UINTN PageCount;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS DstBuffer;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
UINTN PageCount;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS DstBuffer;

DEBUG ((DEBUG_INFO, "MmLoadImage - %g\n", &DriverEntry->FileName));

if (ImageContext == NULL) {
return EFI_INVALID_PARAMETER;
}

Status = EFI_SUCCESS;

//
// Initialize ImageContext
//
ImageContext.Handle = DriverEntry->Pe32Data;
ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
ImageContext->Handle = DriverEntry->Pe32Data;
ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;

//
// Get information about the image being loaded
//
Status = PeCoffLoaderGetImageInfo (&ImageContext);
Status = PeCoffLoaderGetImageInfo (ImageContext);
if (EFI_ERROR (Status)) {
return Status;
}

PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);
PageCount = (UINTN)EFI_SIZE_TO_PAGES ((UINTN)ImageContext->ImageSize + ImageContext->SectionAlignment);
DstBuffer = (UINTN)(-1);

Status = MmAllocatePages (
Expand All @@ -148,18 +153,18 @@ MmLoadImage (
return Status;
}

ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
ImageContext->ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;

//
// Align buffer on section boundary
//
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)(ImageContext.SectionAlignment - 1));
ImageContext->ImageAddress += ImageContext->SectionAlignment - 1;
ImageContext->ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)(ImageContext->SectionAlignment - 1));

//
// Load the image to our new buffer
//
Status = PeCoffLoaderLoadImage (&ImageContext);
Status = PeCoffLoaderLoadImage (ImageContext);
if (EFI_ERROR (Status)) {
MmFreePages (DstBuffer, PageCount);
return Status;
Expand All @@ -168,21 +173,23 @@ MmLoadImage (
//
// Relocate the image in our new buffer
//
Status = PeCoffLoaderRelocateImage (&ImageContext);
Status = PeCoffLoaderRelocateImage (ImageContext);
if (EFI_ERROR (Status)) {
// if relocate fails, we don't need to call unload image here, as the extra action that may change page attributes
// only is called on a successful return
MmFreePages (DstBuffer, PageCount);
return Status;
}

//
// Flush the instruction cache so the image data are written before we execute it
//
InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext->ImageAddress, (UINTN)ImageContext->ImageSize);

//
// Save Image EntryPoint in DriverEntry
//
DriverEntry->ImageEntryPoint = ImageContext.EntryPoint;
DriverEntry->ImageEntryPoint = ImageContext->EntryPoint;
DriverEntry->ImageBuffer = DstBuffer;
DriverEntry->NumberOfPage = PageCount;

Expand All @@ -197,7 +204,7 @@ MmLoadImage (
DriverEntry->LoadedImage.FilePath = NULL;

DriverEntry->LoadedImage.ImageBase = (VOID *)(UINTN)DriverEntry->ImageBuffer;
DriverEntry->LoadedImage.ImageSize = ImageContext.ImageSize;
DriverEntry->LoadedImage.ImageSize = ImageContext->ImageSize;
DriverEntry->LoadedImage.ImageCodeType = EfiRuntimeServicesCode;
DriverEntry->LoadedImage.ImageDataType = EfiRuntimeServicesData;

Expand All @@ -223,18 +230,18 @@ MmLoadImage (
DEBUG ((
DEBUG_INFO | DEBUG_LOAD,
"Loading MM driver at 0x%11p EntryPoint=0x%11p ",
(VOID *)(UINTN)ImageContext.ImageAddress,
FUNCTION_ENTRY_POINT (ImageContext.EntryPoint)
(VOID *)(UINTN)ImageContext->ImageAddress,
FUNCTION_ENTRY_POINT (ImageContext->EntryPoint)
));

//
// Print Module Name by Pdb file path.
// Windows and Unix style file path are all trimmed correctly.
//
if (ImageContext.PdbPointer != NULL) {
if (ImageContext->PdbPointer != NULL) {
StartIndex = 0;
for (Index = 0; ImageContext.PdbPointer[Index] != 0; Index++) {
if ((ImageContext.PdbPointer[Index] == '\\') || (ImageContext.PdbPointer[Index] == '/')) {
for (Index = 0; ImageContext->PdbPointer[Index] != 0; Index++) {
if ((ImageContext->PdbPointer[Index] == '\\') || (ImageContext->PdbPointer[Index] == '/')) {
StartIndex = Index + 1;
}
}
Expand All @@ -245,7 +252,7 @@ MmLoadImage (
// If the length is bigger than 255, trim the redundant characters to avoid overflow in array boundary.
//
for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {
EfiFileName[Index] = ImageContext.PdbPointer[Index + StartIndex];
EfiFileName[Index] = ImageContext->PdbPointer[Index + StartIndex];
if (EfiFileName[Index] == 0) {
EfiFileName[Index] = '.';
}
Expand Down Expand Up @@ -381,11 +388,12 @@ MmDispatcher (
VOID
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
EFI_MM_DRIVER_ENTRY *DriverEntry;
BOOLEAN ReadyToRun;
BOOLEAN PreviousMmEntryPointRegistered;
EFI_STATUS Status;
LIST_ENTRY *Link;
EFI_MM_DRIVER_ENTRY *DriverEntry;
BOOLEAN ReadyToRun;
BOOLEAN PreviousMmEntryPointRegistered;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;

DEBUG ((DEBUG_INFO, "MmDispatcher\n"));

Expand Down Expand Up @@ -424,7 +432,7 @@ MmDispatcher (
// skip the LoadImage
//
if (DriverEntry->ImageHandle == NULL) {
Status = MmLoadImage (DriverEntry);
Status = MmLoadImage (DriverEntry, &ImageContext);

//
// Update the driver state to reflect that it's been loaded
Expand Down Expand Up @@ -461,6 +469,11 @@ MmDispatcher (
Status = ((MM_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle, &gMmCoreMmst);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "StartImage Status - %r\n", Status));

// we need to unload the image before we free the pages. On some architectures (e.g. x86), this is a no-op, but
// on others (e.g. AARCH64) this will remove the image memory protections set on the region so that when the
// memory is freed, it has the default attributes set and can be used generically
PeCoffLoaderUnloadImage (&ImageContext);
MmFreePages (DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);
if (DriverEntry->ImageHandle != NULL) {
MmUninstallProtocolInterface (
Expand Down
Loading