mirror of https://github.com/acidanthera/audk.git
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:
parent
cdc686223a
commit
493f2c6931
|
@ -71,6 +71,7 @@ typedef RETURN_STATUS (*REGION_PERMISSION_UPDATE_FUNC) (
|
||||||
and make further progress in the boot process.
|
and make further progress in the boot process.
|
||||||
|
|
||||||
@param ImageContext Pointer to PE/COFF image context
|
@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 SectionHeaderOffset Offset of PE/COFF image section header
|
||||||
@param NumberOfSections Number of Sections
|
@param NumberOfSections Number of Sections
|
||||||
@param TextUpdater Function to change code permissions
|
@param TextUpdater Function to change code permissions
|
||||||
|
@ -82,6 +83,7 @@ EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
UpdateMmFoundationPeCoffPermissions (
|
UpdateMmFoundationPeCoffPermissions (
|
||||||
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS ImageBase,
|
||||||
IN UINT32 SectionHeaderOffset,
|
IN UINT32 SectionHeaderOffset,
|
||||||
IN CONST UINT16 NumberOfSections,
|
IN CONST UINT16 NumberOfSections,
|
||||||
IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
|
IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
|
||||||
|
@ -98,6 +100,7 @@ UpdateMmFoundationPeCoffPermissions (
|
||||||
|
|
||||||
@param TeData Pointer to PE/COFF image data
|
@param TeData Pointer to PE/COFF image data
|
||||||
@param ImageContext Pointer to PE/COFF image context
|
@param ImageContext Pointer to PE/COFF image context
|
||||||
|
@param ImageBase Pointer to ImageBase variable
|
||||||
@param SectionHeaderOffset Offset of PE/COFF image section header
|
@param SectionHeaderOffset Offset of PE/COFF image section header
|
||||||
@param NumberOfSections Number of Sections
|
@param NumberOfSections Number of Sections
|
||||||
|
|
||||||
|
@ -107,6 +110,7 @@ EFIAPI
|
||||||
GetStandaloneMmCorePeCoffSections (
|
GetStandaloneMmCorePeCoffSections (
|
||||||
IN VOID *TeData,
|
IN VOID *TeData,
|
||||||
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
||||||
|
OUT EFI_PHYSICAL_ADDRESS *ImageBase,
|
||||||
IN OUT UINT32 *SectionHeaderOffset,
|
IN OUT UINT32 *SectionHeaderOffset,
|
||||||
IN OUT UINT16 *NumberOfSections
|
IN OUT UINT16 *NumberOfSections
|
||||||
);
|
);
|
||||||
|
|
|
@ -29,6 +29,7 @@ EFI_STATUS
|
||||||
EFIAPI
|
EFIAPI
|
||||||
UpdateMmFoundationPeCoffPermissions (
|
UpdateMmFoundationPeCoffPermissions (
|
||||||
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS ImageBase,
|
||||||
IN UINT32 SectionHeaderOffset,
|
IN UINT32 SectionHeaderOffset,
|
||||||
IN CONST UINT16 NumberOfSections,
|
IN CONST UINT16 NumberOfSections,
|
||||||
IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
|
IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
|
||||||
|
@ -87,7 +88,7 @@ UpdateMmFoundationPeCoffPermissions (
|
||||||
// if it is a writeable section then mark it appropriately as well.
|
// if it is a writeable section then mark it appropriately as well.
|
||||||
//
|
//
|
||||||
if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
|
if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
|
||||||
Base = ImageContext->ImageAddress + SectionHeader.VirtualAddress;
|
Base = ImageBase + SectionHeader.VirtualAddress;
|
||||||
|
|
||||||
TextUpdater (Base, SectionHeader.Misc.VirtualSize);
|
TextUpdater (Base, SectionHeader.Misc.VirtualSize);
|
||||||
|
|
||||||
|
@ -153,6 +154,7 @@ STATIC
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
GetPeCoffSectionInformation (
|
GetPeCoffSectionInformation (
|
||||||
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
||||||
|
OUT EFI_PHYSICAL_ADDRESS *ImageBase,
|
||||||
OUT UINT32 *SectionHeaderOffset,
|
OUT UINT32 *SectionHeaderOffset,
|
||||||
OUT UINT16 *NumberOfSections
|
OUT UINT16 *NumberOfSections
|
||||||
)
|
)
|
||||||
|
@ -212,6 +214,7 @@ GetPeCoffSectionInformation (
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*ImageBase = ImageContext->ImageAddress;
|
||||||
if (!ImageContext->IsTeImage) {
|
if (!ImageContext->IsTeImage) {
|
||||||
ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);
|
ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);
|
||||||
|
|
||||||
|
@ -232,7 +235,7 @@ GetPeCoffSectionInformation (
|
||||||
} else {
|
} else {
|
||||||
*SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
|
*SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
|
||||||
*NumberOfSections = Hdr.Te->NumberOfSections;
|
*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;
|
return RETURN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -242,6 +245,7 @@ EFIAPI
|
||||||
GetStandaloneMmCorePeCoffSections (
|
GetStandaloneMmCorePeCoffSections (
|
||||||
IN VOID *TeData,
|
IN VOID *TeData,
|
||||||
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
|
||||||
|
OUT EFI_PHYSICAL_ADDRESS *ImageBase,
|
||||||
IN OUT UINT32 *SectionHeaderOffset,
|
IN OUT UINT32 *SectionHeaderOffset,
|
||||||
IN OUT UINT16 *NumberOfSections
|
IN OUT UINT16 *NumberOfSections
|
||||||
)
|
)
|
||||||
|
@ -255,7 +259,8 @@ GetStandaloneMmCorePeCoffSections (
|
||||||
|
|
||||||
DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));
|
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)) {
|
if (EFI_ERROR (Status)) {
|
||||||
DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));
|
DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));
|
||||||
return Status;
|
return Status;
|
||||||
|
|
|
@ -225,6 +225,7 @@ _ModuleEntryPoint (
|
||||||
VOID *HobStart;
|
VOID *HobStart;
|
||||||
VOID *TeData;
|
VOID *TeData;
|
||||||
UINTN TeDataSize;
|
UINTN TeDataSize;
|
||||||
|
EFI_PHYSICAL_ADDRESS ImageBase;
|
||||||
|
|
||||||
// Get Secure Partition Manager Version Information
|
// Get Secure Partition Manager Version Information
|
||||||
Status = GetSpmVersion ();
|
Status = GetSpmVersion ();
|
||||||
|
@ -253,6 +254,7 @@ _ModuleEntryPoint (
|
||||||
Status = GetStandaloneMmCorePeCoffSections (
|
Status = GetStandaloneMmCorePeCoffSections (
|
||||||
TeData,
|
TeData,
|
||||||
&ImageContext,
|
&ImageContext,
|
||||||
|
&ImageBase,
|
||||||
&SectionHeaderOffset,
|
&SectionHeaderOffset,
|
||||||
&NumberOfSections
|
&NumberOfSections
|
||||||
);
|
);
|
||||||
|
@ -261,10 +263,21 @@ _ModuleEntryPoint (
|
||||||
goto finish;
|
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
|
// Update the memory access permissions of individual sections in the
|
||||||
// Standalone MM core module
|
// Standalone MM core module
|
||||||
Status = UpdateMmFoundationPeCoffPermissions (
|
Status = UpdateMmFoundationPeCoffPermissions (
|
||||||
&ImageContext,
|
&ImageContext,
|
||||||
|
ImageBase,
|
||||||
SectionHeaderOffset,
|
SectionHeaderOffset,
|
||||||
NumberOfSections,
|
NumberOfSections,
|
||||||
ArmSetMemoryRegionNoExec,
|
ArmSetMemoryRegionNoExec,
|
||||||
|
@ -276,6 +289,15 @@ _ModuleEntryPoint (
|
||||||
goto finish;
|
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
|
// Create Hoblist based upon boot information passed by privileged software
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue