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>
---
StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h | 2 ++
StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c | 11 +++++++---
StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c | 22 ++++++++++++++++++++
3 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h b/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
index 494bcf3dc28f..a3420699e6f1 100644
--- a/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
+++ b/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
@@ -82,6 +82,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,
@@ -107,6 +108,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
);
diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
index 00f49c9d0558..bf9650d54629 100644
--- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
+++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
@@ -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;
diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c
index 20723385113f..9cecfa667b90 100644
--- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c
+++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c
@@ -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
//
--
2.26.2
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#61043): https://edk2.groups.io/g/devel/message/61043
Mute This Topic: https://groups.io/mt/74792292/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
I hope ARM expert can review this to double confirm.
Thank you
Yao Jiewen
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Ard
> Biesheuvel
> Sent: Wednesday, June 10, 2020 4:18 PM
> To: devel@edk2.groups.io
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Gao, Liming <liming.gao@intel.com>; Yao,
> Jiewen <jiewen.yao@intel.com>; Sami Mujawar <sami.mujawar@arm.com>;
> Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Subject: [edk2-devel] [PATCH 5/5]
> 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>
> ---
> StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
> | 2 ++
>
> StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissi
> ons.c | 11 +++++++---
>
> StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/Standalone
> MmCoreEntryPoint.c | 22 ++++++++++++++++++++
> 3 files changed, 32 insertions(+), 3 deletions(-)
>
> diff --git
> a/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
> b/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
> index 494bcf3dc28f..a3420699e6f1 100644
> ---
> a/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
> +++
> b/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
> @@ -82,6 +82,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,
>
> @@ -107,6 +108,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
>
> );
>
> diff --git
> a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermis
> sions.c
> b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermis
> sions.c
> index 00f49c9d0558..bf9650d54629 100644
> ---
> a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermis
> sions.c
> +++
> b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermis
> sions.c
> @@ -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;
>
> diff --git
> a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/Standalon
> eMmCoreEntryPoint.c
> b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/Standalon
> eMmCoreEntryPoint.c
> index 20723385113f..9cecfa667b90 100644
> ---
> a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/Standalon
> eMmCoreEntryPoint.c
> +++
> b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/Standalon
> eMmCoreEntryPoint.c
> @@ -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
>
> //
>
> --
> 2.26.2
>
>
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
>
> View/Reply Online (#61043): https://edk2.groups.io/g/devel/message/61043
> Mute This Topic: https://groups.io/mt/74792292/1772286
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub [jiewen.yao@intel.com]
> -=-=-=-=-=-=
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#61241): https://edk2.groups.io/g/devel/message/61241
Mute This Topic: https://groups.io/mt/74792292/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Apologies for top replying. I am not sure if it is my setup where I see additional characters (e.g. =0D at the end of each line) which appear to confuse my email client. > UpdateMmFoundationPeCoffPermissions (=0D > IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,=0D > + IN EFI_PHYSICAL_ADDRESS ImageBase,=0D Can the function documentation for UpdateMmFoundationPeCoffPermissions() and GetStandaloneMmCorePeCoffSections() be updated to reflect the additional parameter ImageBase, please? On Wed, Jun 10, 2020 at 01:17 AM, Ard Biesheuvel wrote: > > + *ImageBase =3D ImageContext->ImageAddress;=0D I think the '*ImageBase = ImageContext->ImageAddress;' statement can be moved inside the if condition. With these changes. Reviewed-by: Sami Mujawar <sami.mujawar@arm.com> Sami Mujawar -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#61290): https://edk2.groups.io/g/devel/message/61290 Mute This Topic: https://groups.io/mt/74792292/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
On 6/15/20 3:59 PM, Sami Mujawar via Groups.Io wrote: > Apologies for top replying. I am not sure if it is my setup where I see > additional characters (e.g. =0D at the end of each line) which appear to > confuse my email client. > That must be Thunderbird playing tricks. > > > UpdateMmFoundationPeCoffPermissions (=0D > > IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,=0D > > + IN EFI_PHYSICAL_ADDRESS ImageBase,=0D > Can the function documentation for UpdateMmFoundationPeCoffPermissions() > and GetStandaloneMmCorePeCoffSections() be updated to reflect the > additional parameter ImageBase, please? > Sure > On Wed, Jun 10, 2020 at 01:17 AM, Ard Biesheuvel wrote: > > + *ImageBase =3D ImageContext->ImageAddress;=0D > > I think the '*ImageBase = ImageContext->ImageAddress;' statement can be > moved inside the if condition. No, the TE branch of the if() does a subtraction so it needs the value to be set beforehand. > With these changes. > > Reviewed-by: Sami Mujawar <sami.mujawar@arm.com> > > Sami Mujawar -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#61299): https://edk2.groups.io/g/devel/message/61299 Mute This Topic: https://groups.io/mt/74792292/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
On Mon, Jun 15, 2020 at 07:12 AM, Ard Biesheuvel wrote: > > >> On Wed, Jun 10, 2020 at 01:17 AM, Ard Biesheuvel wrote: >> + *ImageBase =3D ImageContext->ImageAddress;=0D >> I think the '*ImageBase = ImageContext->ImageAddress;' statement can be >> moved inside the if condition. > > No, the TE branch of the if() does a subtraction so it needs the value to > be set beforehand. Sorry, I missed the -=. Please ignore. Regards, Sami Mujawar -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#61300): https://edk2.groups.io/g/devel/message/61300 Mute This Topic: https://groups.io/mt/74792292/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2026 Red Hat, Inc.