@@ -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
);
/**
@@ -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;
@@ -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 ;
}
@@ -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
);
@@ -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
@@ -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;
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 <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(-)