StandaloneMmPkg/StandaloneMmCoreEntryPoint: relocate StMM core on the fly

Apply PE/COFF fixups when starting up the standalone MM core, so that
it can execute at any address regardless of the link time address.

Note that this requires the PE/COFF image to be emitted with its
relocation section preserved. Special care is taken to ensure that
TE images are dealt with correctly as well.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
Tested-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
This commit is contained in:
Ard Biesheuvel 2020-06-09 10:34:27 +02:00 committed by mergify[bot]
parent cdc686223a
commit 493f2c6931
3 changed files with 34 additions and 3 deletions

View File

@ -71,6 +71,7 @@ typedef RETURN_STATUS (*REGION_PERMISSION_UPDATE_FUNC) (
and make further progress in the boot process.
@param ImageContext Pointer to PE/COFF image context
@param ImageBase Base of image in memory
@param SectionHeaderOffset Offset of PE/COFF image section header
@param NumberOfSections Number of Sections
@param TextUpdater Function to change code permissions
@ -82,6 +83,7 @@ EFI_STATUS
EFIAPI
UpdateMmFoundationPeCoffPermissions (
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
IN EFI_PHYSICAL_ADDRESS ImageBase,
IN UINT32 SectionHeaderOffset,
IN CONST UINT16 NumberOfSections,
IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
@ -98,6 +100,7 @@ UpdateMmFoundationPeCoffPermissions (
@param TeData Pointer to PE/COFF image data
@param ImageContext Pointer to PE/COFF image context
@param ImageBase Pointer to ImageBase variable
@param SectionHeaderOffset Offset of PE/COFF image section header
@param NumberOfSections Number of Sections
@ -107,6 +110,7 @@ EFIAPI
GetStandaloneMmCorePeCoffSections (
IN VOID *TeData,
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
OUT EFI_PHYSICAL_ADDRESS *ImageBase,
IN OUT UINT32 *SectionHeaderOffset,
IN OUT UINT16 *NumberOfSections
);

View File

@ -29,6 +29,7 @@ EFI_STATUS
EFIAPI
UpdateMmFoundationPeCoffPermissions (
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
IN EFI_PHYSICAL_ADDRESS ImageBase,
IN UINT32 SectionHeaderOffset,
IN CONST UINT16 NumberOfSections,
IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
@ -87,7 +88,7 @@ UpdateMmFoundationPeCoffPermissions (
// if it is a writeable section then mark it appropriately as well.
//
if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
Base = ImageContext->ImageAddress + SectionHeader.VirtualAddress;
Base = ImageBase + SectionHeader.VirtualAddress;
TextUpdater (Base, SectionHeader.Misc.VirtualSize);
@ -153,6 +154,7 @@ STATIC
EFI_STATUS
GetPeCoffSectionInformation (
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
OUT EFI_PHYSICAL_ADDRESS *ImageBase,
OUT UINT32 *SectionHeaderOffset,
OUT UINT16 *NumberOfSections
)
@ -212,6 +214,7 @@ GetPeCoffSectionInformation (
return Status;
}
*ImageBase = ImageContext->ImageAddress;
if (!ImageContext->IsTeImage) {
ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);
@ -232,7 +235,7 @@ GetPeCoffSectionInformation (
} else {
*SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
*NumberOfSections = Hdr.Te->NumberOfSections;
ImageContext->ImageAddress -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
*ImageBase -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
}
return RETURN_SUCCESS;
}
@ -242,6 +245,7 @@ EFIAPI
GetStandaloneMmCorePeCoffSections (
IN VOID *TeData,
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
OUT EFI_PHYSICAL_ADDRESS *ImageBase,
IN OUT UINT32 *SectionHeaderOffset,
IN OUT UINT16 *NumberOfSections
)
@ -255,7 +259,8 @@ GetStandaloneMmCorePeCoffSections (
DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));
Status = GetPeCoffSectionInformation (ImageContext, SectionHeaderOffset, NumberOfSections);
Status = GetPeCoffSectionInformation (ImageContext, ImageBase,
SectionHeaderOffset, NumberOfSections);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));
return Status;

View File

@ -225,6 +225,7 @@ _ModuleEntryPoint (
VOID *HobStart;
VOID *TeData;
UINTN TeDataSize;
EFI_PHYSICAL_ADDRESS ImageBase;
// Get Secure Partition Manager Version Information
Status = GetSpmVersion ();
@ -253,6 +254,7 @@ _ModuleEntryPoint (
Status = GetStandaloneMmCorePeCoffSections (
TeData,
&ImageContext,
&ImageBase,
&SectionHeaderOffset,
&NumberOfSections
);
@ -261,10 +263,21 @@ _ModuleEntryPoint (
goto finish;
}
//
// ImageBase may deviate from ImageContext.ImageAddress if we are dealing
// with a TE image, in which case the latter points to the actual offset
// of the image, whereas ImageBase refers to the address where the image
// would start if the stripped PE headers were still in place. In either
// case, we need to fix up ImageBase so it refers to the actual current
// load address.
//
ImageBase += (UINTN)TeData - ImageContext.ImageAddress;
// Update the memory access permissions of individual sections in the
// Standalone MM core module
Status = UpdateMmFoundationPeCoffPermissions (
&ImageContext,
ImageBase,
SectionHeaderOffset,
NumberOfSections,
ArmSetMemoryRegionNoExec,
@ -276,6 +289,15 @@ _ModuleEntryPoint (
goto finish;
}
if (ImageContext.ImageAddress != (UINTN)TeData) {
ImageContext.ImageAddress = (UINTN)TeData;
ArmSetMemoryRegionNoExec (ImageBase, SIZE_4KB);
ArmClearMemoryRegionReadOnly (ImageBase, SIZE_4KB);
Status = PeCoffLoaderRelocateImage (&ImageContext);
ASSERT_EFI_ERROR (Status);
}
//
// Create Hoblist based upon boot information passed by privileged software
//