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.biesheu...@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


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to