The OS is not required to preserve the relative offsets between
RuntimeServicesCode and RuntimeServicesData memory regions when
switching to virtual mode. This does not present any problems as
long as PE/COFF images in memory are covered by only a single region.
However, with the introduction of the MemoryProtectionAttribute feature
in UEFI v2.5, the firmware may decide to split those regions into
separate code and data regions. So rather than reapplying the relocations
for the entire image based on a single adjustment value (which is derived
from the physical to virtual shift of ImageBase), we need to invoke
ConvertPointer () on each relocation target.
So modify PeCoffLoaderRelocateImageForRuntime () to take a callback
function pointer instead of a fixed adjustment value, and invoke the
callback for each re-relocated value.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <***@linaro.org>
---
MdePkg/Include/Library/PeCoffLib.h | 28 ++++++++++++----
MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c | 19 ++++++-----
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 35 +++++++++++---------
MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h | 16 ++++-----
MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c | 32 +++++++++---------
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 16 ++++-----
6 files changed, 83 insertions(+), 63 deletions(-)
diff --git a/MdePkg/Include/Library/PeCoffLib.h b/MdePkg/Include/Library/PeCoffLib.h
index 9ed6d61be01c..ed75f3613306 100644
--- a/MdePkg/Include/Library/PeCoffLib.h
+++ b/MdePkg/Include/Library/PeCoffLib.h
@@ -335,6 +335,22 @@ PeCoffLoaderImageReadFromMemory (
OUT VOID *Buffer
);
+/**
+ Translates a physical to virtual address for PE/COFF runtime re-relocation
+
+ @param[in, out] Address A pointer to a pointer that is to be fixed to be the value needed
+ for the new virtual address mappings being applied.
+
+ @retval EFI_SUCCESS The pointer pointed to by Address was modified.
+ @retval EFI_INVALID_PARAMETER Address is NULL.
+ @retval EFI_NOT_FOUND The value pointed to by Address could not be converted.
+
+**/
+typedef
+RETURN_STATUS
+(EFIAPI *PE_COFF_LOADER_CONVERT_POINTER) (
+ IN OUT VOID **Address
+ );
/**
Reapply fixups on a fixed up PE32/PE32+ image to allow virutal calling at EFI
@@ -352,8 +368,8 @@ PeCoffLoaderImageReadFromMemory (
@param ImageBase The base address of a PE/COFF image that has been loaded
and relocated into system memory.
- @param VirtImageBase The request virtual address that the PE/COFF image is to
- be fixed up for.
+ @param ConvertPointer Address of a PE_COFF_LOADER_CONVERT_POINTER callback function
+ that performs physical to virtual conversions
@param ImageSize The size, in bytes, of the PE/COFF image.
@param RelocationData A pointer to the relocation data that was collected when the PE/COFF
image was relocated using PeCoffLoaderRelocateImage().
@@ -362,10 +378,10 @@ PeCoffLoaderImageReadFromMemory (
VOID
EFIAPI
PeCoffLoaderRelocateImageForRuntime (
- IN PHYSICAL_ADDRESS ImageBase,
- IN PHYSICAL_ADDRESS VirtImageBase,
- IN UINTN ImageSize,
- IN VOID *RelocationData
+ IN PHYSICAL_ADDRESS ImageBase,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer,
+ IN UINTN ImageSize,
+ IN VOID *RelocationData
);
/**
diff --git a/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c
index d6bf42738d2b..ba09e1f16018 100644
--- a/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c
@@ -205,20 +205,20 @@ PeCoffLoaderImageFormatSupported (
instruction sets. This is used to re-relocated the image into the EFI virtual
space for runtime calls.
- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
+ @param Reloc The pointer to the relocation record.
+ @param Fixup The pointer to the address to fix up.
+ @param FixupData The pointer to a buffer to log the fixups.
+ @param ConvertPointer Pointer to a physical to virtual conversion function
@return Status code.
**/
RETURN_STATUS
PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer
)
{
UINT16 *Fixup16;
@@ -231,7 +231,8 @@ PeHotRelocateImageEx (
case EFI_IMAGE_REL_BASED_ARM_MOV32T:
*FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));
if (*(UINT64 *) (*FixupData) == ReadUnaligned64 ((UINT64 *)Fixup16)) {
- FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust;
+ FixupVal = ThumbMovwMovtImmediateAddress (Fixup16);
+ ConvertPointer ((VOID **) &FixupVal);
ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);
}
break;
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
index 23cb691ad729..e4de6fae7ce9 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
@@ -1692,8 +1692,8 @@ PeCoffLoaderLoadImage (
@param ImageBase The base address of a PE/COFF image that has been loaded
and relocated into system memory.
- @param VirtImageBase The request virtual address that the PE/COFF image is to
- be fixed up for.
+ @param ConvertPointer Address of a PE_COFF_LOADER_CONVERT_POINTER callback function
+ that performs physical to virtual conversions
@param ImageSize The size, in bytes, of the PE/COFF image.
@param RelocationData A pointer to the relocation data that was collected when the PE/COFF
image was relocated using PeCoffLoaderRelocateImage().
@@ -1702,14 +1702,13 @@ PeCoffLoaderLoadImage (
VOID
EFIAPI
PeCoffLoaderRelocateImageForRuntime (
- IN PHYSICAL_ADDRESS ImageBase,
- IN PHYSICAL_ADDRESS VirtImageBase,
- IN UINTN ImageSize,
- IN VOID *RelocationData
+ IN PHYSICAL_ADDRESS ImageBase,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer,
+ IN UINTN ImageSize,
+ IN VOID *RelocationData
)
{
CHAR8 *OldBase;
- CHAR8 *NewBase;
EFI_IMAGE_DOS_HEADER *DosHdr;
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
UINT32 NumberOfRvaAndSizes;
@@ -1725,15 +1724,13 @@ PeCoffLoaderRelocateImageForRuntime (
UINT32 *Fixup32;
UINT64 *Fixup64;
CHAR8 *FixupData;
- UINTN Adjust;
RETURN_STATUS Status;
UINT16 Magic;
UINT8 HighLowMask [SIZE_4KB / (8 * sizeof(UINT32))];
UINTN HighLowMaskIndex;
+ UINTN ConvertAddress;
OldBase = (CHAR8 *)((UINTN)ImageBase);
- NewBase = (CHAR8 *)((UINTN)VirtImageBase);
- Adjust = (UINTN) NewBase - (UINTN) OldBase;
//
// Find the image's relocate dir info
@@ -1842,7 +1839,9 @@ PeCoffLoaderRelocateImageForRuntime (
if (*(UINT32 *) FixupData == *Fixup32 ||
(HighLowMask [HighLowMaskIndex >> 3] & (1 << (HighLowMaskIndex & 7))) != 0) {
- *Fixup16 = (UINT16) ((*Fixup32 + (UINT32) Adjust) >> 16);
+ ConvertAddress = *(UINT32 *) FixupData;
+ ConvertPointer ((VOID **) &ConvertAddress);
+ *Fixup16 = (UINT16) (ConvertAddress >> 16);
//
// Mark this location in the page as requiring the low relocation to
@@ -1862,7 +1861,9 @@ PeCoffLoaderRelocateImageForRuntime (
if (*(UINT32 *) FixupData == *(UINT32 *)Fixup ||
(HighLowMask [HighLowMaskIndex >> 3] & (1 << (HighLowMaskIndex & 7))) != 0) {
- *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff));
+ ConvertAddress = *(UINT32 *) FixupData;
+ ConvertPointer ((VOID **) &ConvertAddress);
+ *Fixup16 = (UINT16) (ConvertAddress & 0xffff);
//
// Mark this location in the page as requiring the high relocation to
@@ -1879,7 +1880,9 @@ PeCoffLoaderRelocateImageForRuntime (
Fixup32 = (UINT32 *) Fixup;
FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
if (*(UINT32 *) FixupData == *Fixup32) {
- *Fixup32 = *Fixup32 + (UINT32) Adjust;
+ ConvertAddress = *Fixup32;
+ ConvertPointer ((VOID **) &ConvertAddress);
+ *Fixup32 = (UINT32) ConvertAddress;
}
FixupData = FixupData + sizeof (UINT32);
@@ -1889,7 +1892,9 @@ PeCoffLoaderRelocateImageForRuntime (
Fixup64 = (UINT64 *)Fixup;
FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));
if (*(UINT64 *) FixupData == *Fixup64) {
- *Fixup64 = *Fixup64 + (UINT64)Adjust;
+ ConvertAddress = (UINTN) *Fixup64;
+ ConvertPointer ((VOID **) &ConvertAddress);
+ *Fixup64 = ConvertAddress;
}
FixupData = FixupData + sizeof (UINT64);
@@ -1899,7 +1904,7 @@ PeCoffLoaderRelocateImageForRuntime (
//
// Only Itanium requires ConvertPeImage_Ex
//
- Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
+ Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, ConvertPointer);
if (RETURN_ERROR (Status)) {
return ;
}
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h b/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h
index 0851acc18c19..9ffc59318f9b 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h
@@ -50,20 +50,20 @@ PeCoffLoaderRelocateImageEx (
instruction sets. This is used to re-relocated the image into the EFI virtual
space for runtime calls.
- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
+ @param Reloc The pointer to the relocation record.
+ @param Fixup The pointer to the address to fix up.
+ @param FixupData The pointer to a buffer to log the fixups.
+ @param ConvertPointer Pointer to a physical to virtual conversion function
@return Status code.
**/
RETURN_STATUS
PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer
);
diff --git a/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
index a590f3906fab..bd371a33a445 100644
--- a/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
@@ -242,25 +242,23 @@ PeCoffLoaderImageFormatSupported (
/**
- ImageRead function that operates on a memory buffer whos base is passed into
- FileHandle.
-
- @param Reloc Ponter to baes of the input stream
- @param Fixup Offset to the start of the buffer
- @param FixupData The number of bytes to copy into the buffer
- @param Adjust Location to place results of read
-
- @retval RETURN_SUCCESS Data is read from FileOffset from the Handle into
- the buffer.
- @retval RETURN_UNSUPPORTED Un-recoganized relocation entry
- type.
+ Performs an Itanium-based specific re-relocation fixup and is a no-op on other
+ instruction sets. This is used to re-relocated the image into the EFI virtual
+ space for runtime calls.
+
+ @param Reloc The pointer to the relocation record.
+ @param Fixup The pointer to the address to fix up.
+ @param FixupData The pointer to a buffer to log the fixups.
+ @param ConvertPointer Pointer to a physical to virtual conversion function
+
+ @return Status code.
**/
RETURN_STATUS
PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer
)
{
UINT64 *Fixup64;
@@ -325,7 +323,7 @@ PeHotRelocateImageEx (
//
// Update 64-bit address
//
- FixupVal += Adjust;
+ ConvertPointer ((VOID **) &FixupVal);
//
// Insert IMM64 into bundle
diff --git a/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
index 01825c85392b..8ddf6fe722f8 100644
--- a/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
@@ -69,20 +69,20 @@ PeCoffLoaderImageFormatSupported (
instruction sets. This is used to re-relocated the image into the EFI virtual
space for runtime calls.
- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
+ @param Reloc The pointer to the relocation record.
+ @param Fixup The pointer to the address to fix up.
+ @param FixupData The pointer to a buffer to log the fixups.
+ @param ConvertPointer Pointer to a physical to virtual conversion function
@return Status code.
**/
RETURN_STATUS
PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer
)
{
return RETURN_UNSUPPORTED;
--
1.9.1