]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OldMdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
Moved the MdePkg to OldMdePkg so that new code in MdePkg does not break existing...
[mirror_edk2.git] / OldMdePkg / Library / BasePeCoffLib / Ipf / PeCoffLoaderEx.c
diff --git a/OldMdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c b/OldMdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
new file mode 100644 (file)
index 0000000..065aec4
--- /dev/null
@@ -0,0 +1,424 @@
+/** @file\r
+  Fixes Intel Itanium(TM) specific relocation types.\r
+\r
+  Copyright (c) 2006, Intel Corporation\r
+  All rights reserved. This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+  Module Name:  PeCoffLoaderEx.c\r
+\r
+**/\r
+\r
+#include "BasePeCoffLibInternals.h"\r
+\r
+\r
+\r
+#define EXT_IMM64(Value, Address, Size, InstPos, ValPos)  \\r
+    Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)\r
+\r
+#define INS_IMM64(Value, Address, Size, InstPos, ValPos)  \\r
+    *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \\r
+          ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)\r
+\r
+#define IMM64_IMM7B_INST_WORD_X         3\r
+#define IMM64_IMM7B_SIZE_X              7\r
+#define IMM64_IMM7B_INST_WORD_POS_X     4\r
+#define IMM64_IMM7B_VAL_POS_X           0\r
+\r
+#define IMM64_IMM9D_INST_WORD_X         3\r
+#define IMM64_IMM9D_SIZE_X              9\r
+#define IMM64_IMM9D_INST_WORD_POS_X     18\r
+#define IMM64_IMM9D_VAL_POS_X           7\r
+\r
+#define IMM64_IMM5C_INST_WORD_X         3\r
+#define IMM64_IMM5C_SIZE_X              5\r
+#define IMM64_IMM5C_INST_WORD_POS_X     13\r
+#define IMM64_IMM5C_VAL_POS_X           16\r
+\r
+#define IMM64_IC_INST_WORD_X            3\r
+#define IMM64_IC_SIZE_X                 1\r
+#define IMM64_IC_INST_WORD_POS_X        12\r
+#define IMM64_IC_VAL_POS_X              21\r
+\r
+#define IMM64_IMM41a_INST_WORD_X        1\r
+#define IMM64_IMM41a_SIZE_X             10\r
+#define IMM64_IMM41a_INST_WORD_POS_X    14\r
+#define IMM64_IMM41a_VAL_POS_X          22\r
+\r
+#define IMM64_IMM41b_INST_WORD_X        1\r
+#define IMM64_IMM41b_SIZE_X             8\r
+#define IMM64_IMM41b_INST_WORD_POS_X    24\r
+#define IMM64_IMM41b_VAL_POS_X          32\r
+\r
+#define IMM64_IMM41c_INST_WORD_X        2\r
+#define IMM64_IMM41c_SIZE_X             23\r
+#define IMM64_IMM41c_INST_WORD_POS_X    0\r
+#define IMM64_IMM41c_VAL_POS_X          40\r
+\r
+#define IMM64_SIGN_INST_WORD_X          3\r
+#define IMM64_SIGN_SIZE_X               1\r
+#define IMM64_SIGN_INST_WORD_POS_X      27\r
+#define IMM64_SIGN_VAL_POS_X            63\r
+\r
+/**\r
+  Performs an Itanium-based specific relocation fixup.\r
+\r
+  @param  Reloc       Pointer to the relocation record.\r
+  @param  Fixup       Pointer to the address to fix up.\r
+  @param  FixupData   Pointer to a buffer to log the fixups.\r
+  @param  Adjust      The offset to adjust the fixup.\r
+\r
+  @return Status code.\r
+\r
+**/\r
+RETURN_STATUS\r
+PeCoffLoaderRelocateImageEx (\r
+  IN UINT16      *Reloc,\r
+  IN OUT CHAR8   *Fixup,\r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  )\r
+{\r
+  UINT64      *F64;\r
+  UINT64      FixupVal;\r
+\r
+  switch ((*Reloc) >> 12) {\r
+    case EFI_IMAGE_REL_BASED_IA64_IMM64:\r
+\r
+      //\r
+      // Align it to bundle address before fixing up the\r
+      // 64-bit immediate value of the movl instruction.\r
+      //\r
+\r
+      Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));\r
+      FixupVal = (UINT64)0;\r
+\r
+      //\r
+      // Extract the lower 32 bits of IMM64 from bundle\r
+      //\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,\r
+                IMM64_IMM7B_SIZE_X,\r
+                IMM64_IMM7B_INST_WORD_POS_X,\r
+                IMM64_IMM7B_VAL_POS_X\r
+                );\r
+\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,\r
+                IMM64_IMM9D_SIZE_X,\r
+                IMM64_IMM9D_INST_WORD_POS_X,\r
+                IMM64_IMM9D_VAL_POS_X\r
+                );\r
+\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,\r
+                IMM64_IMM5C_SIZE_X,\r
+                IMM64_IMM5C_INST_WORD_POS_X,\r
+                IMM64_IMM5C_VAL_POS_X\r
+                );\r
+\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,\r
+                IMM64_IC_SIZE_X,\r
+                IMM64_IC_INST_WORD_POS_X,\r
+                IMM64_IC_VAL_POS_X\r
+                );\r
+\r
+      EXT_IMM64(FixupVal,\r
+                (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X,\r
+                IMM64_IMM41a_SIZE_X,\r
+                IMM64_IMM41a_INST_WORD_POS_X,\r
+                IMM64_IMM41a_VAL_POS_X\r
+                );\r
+\r
+      //\r
+      // Update 64-bit address\r
+      //\r
+      FixupVal += Adjust;\r
+\r
+      //\r
+      // Insert IMM64 into bundle\r
+      //\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),\r
+                IMM64_IMM7B_SIZE_X,\r
+                IMM64_IMM7B_INST_WORD_POS_X,\r
+                IMM64_IMM7B_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),\r
+                IMM64_IMM9D_SIZE_X,\r
+                IMM64_IMM9D_INST_WORD_POS_X,\r
+                IMM64_IMM9D_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),\r
+                IMM64_IMM5C_SIZE_X,\r
+                IMM64_IMM5C_INST_WORD_POS_X,\r
+                IMM64_IMM5C_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),\r
+                IMM64_IC_SIZE_X,\r
+                IMM64_IC_INST_WORD_POS_X,\r
+                IMM64_IC_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X),\r
+                IMM64_IMM41a_SIZE_X,\r
+                IMM64_IMM41a_INST_WORD_POS_X,\r
+                IMM64_IMM41a_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X),\r
+                IMM64_IMM41b_SIZE_X,\r
+                IMM64_IMM41b_INST_WORD_POS_X,\r
+                IMM64_IMM41b_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X),\r
+                IMM64_IMM41c_SIZE_X,\r
+                IMM64_IMM41c_INST_WORD_POS_X,\r
+                IMM64_IMM41c_VAL_POS_X\r
+                );\r
+\r
+      INS_IMM64(FixupVal,\r
+                ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),\r
+                IMM64_SIGN_SIZE_X,\r
+                IMM64_SIGN_INST_WORD_POS_X,\r
+                IMM64_SIGN_VAL_POS_X\r
+                );\r
+\r
+      F64 = (UINT64 *) Fixup;\r
+      if (*FixupData != NULL) {\r
+        *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));\r
+        *(UINT64 *)(*FixupData) = *F64;\r
+        *FixupData = *FixupData + sizeof(UINT64);\r
+      }\r
+      break;\r
+\r
+    default:\r
+      return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+  Returns TRUE if the machine type of PE/COFF image is supported. Supported\r
+  does not mean the image can be executed it means the PE/COFF loader supports\r
+  loading and relocating of the image type. It's up to the caller to support\r
+  the entry point.\r
+\r
+  This function implies the basic PE/COFF loader/relocator supports IA32, EBC,\r
+  & X64 images. Calling the entry point in a correct mannor is up to the\r
+  consumer of this library. This version also supports the special relocations\r
+  for Itanium.\r
+\r
+  @param  Machine   Machine type from the PE Header.\r
+\r
+  @return TRUE if this PE/COFF loader can load the image\r
+\r
+**/\r
+BOOLEAN\r
+PeCoffLoaderImageFormatSupported (\r
+  IN  UINT16  Machine\r
+  )\r
+{\r
+  if ((Machine == EFI_IMAGE_MACHINE_IPF) || (Machine == EFI_IMAGE_MACHINE_IA32) ||\r
+      (Machine ==  EFI_IMAGE_MACHINE_EBC) || (Machine == EFI_IMAGE_MACHINE_X64)) {\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+/**\r
+  ImageRead function that operates on a memory buffer whos base is passed into\r
+  FileHandle.\r
+\r
+  @param  Reloc             Ponter to baes of the input stream\r
+  @param  Fixup             Offset to the start of the buffer\r
+  @param  FixupData         Number of bytes to copy into the buffer\r
+  @param  Adjust            Location to place results of read\r
+\r
+  @retval RETURN_SUCCESS    Data is read from FileOffset from the Handle into\r
+                            the buffer.\r
+**/\r
+RETURN_STATUS\r
+PeHotRelocateImageEx (\r
+  IN UINT16      *Reloc,\r
+  IN OUT CHAR8   *Fixup,\r
+  IN OUT CHAR8   **FixupData,\r
+  IN UINT64      Adjust\r
+  )\r
+{\r
+  UINT64  *F64;\r
+  UINT64  FixupVal;\r
+\r
+  switch ((*Reloc) >> 12) {\r
+  case EFI_IMAGE_REL_BASED_DIR64:\r
+    F64         = (UINT64 *) Fixup;\r
+    *FixupData  = ALIGN_POINTER (*FixupData, sizeof (UINT64));\r
+    if (*(UINT64 *) (*FixupData) == *F64) {\r
+      *F64 = *F64 + (UINT64) Adjust;\r
+    }\r
+\r
+    *FixupData = *FixupData + sizeof (UINT64);\r
+    break;\r
+\r
+  case EFI_IMAGE_REL_BASED_IA64_IMM64:\r
+    F64         = (UINT64 *) Fixup;\r
+    *FixupData  = ALIGN_POINTER (*FixupData, sizeof (UINT64));\r
+    if (*(UINT64 *) (*FixupData) == *F64) {\r
+      //\r
+      // Align it to bundle address before fixing up the\r
+      // 64-bit immediate value of the movl instruction.\r
+      //\r
+      //\r
+      Fixup     = (CHAR8 *) ((UINT64) Fixup & (UINT64)~(15));\r
+      FixupVal  = (UINT64) 0;\r
+\r
+      //\r
+      // Extract the lower 32 bits of IMM64 from bundle\r
+      //\r
+      EXT_IMM64 (\r
+        FixupVal,\r
+        (UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X,\r
+        IMM64_IMM7B_SIZE_X,\r
+        IMM64_IMM7B_INST_WORD_POS_X,\r
+        IMM64_IMM7B_VAL_POS_X\r
+        );\r
+\r
+      EXT_IMM64 (\r
+        FixupVal,\r
+        (UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X,\r
+        IMM64_IMM9D_SIZE_X,\r
+        IMM64_IMM9D_INST_WORD_POS_X,\r
+        IMM64_IMM9D_VAL_POS_X\r
+        );\r
+\r
+      EXT_IMM64 (\r
+        FixupVal,\r
+        (UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X,\r
+        IMM64_IMM5C_SIZE_X,\r
+        IMM64_IMM5C_INST_WORD_POS_X,\r
+        IMM64_IMM5C_VAL_POS_X\r
+        );\r
+\r
+      EXT_IMM64 (\r
+        FixupVal,\r
+        (UINT32 *) Fixup + IMM64_IC_INST_WORD_X,\r
+        IMM64_IC_SIZE_X,\r
+        IMM64_IC_INST_WORD_POS_X,\r
+        IMM64_IC_VAL_POS_X\r
+        );\r
+\r
+      EXT_IMM64 (\r
+        FixupVal,\r
+        (UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X,\r
+        IMM64_IMM41a_SIZE_X,\r
+        IMM64_IMM41a_INST_WORD_POS_X,\r
+        IMM64_IMM41a_VAL_POS_X\r
+        );\r
+\r
+      //\r
+      // Update 64-bit address\r
+      //\r
+      FixupVal += Adjust;\r
+\r
+      //\r
+      // Insert IMM64 into bundle\r
+      //\r
+      INS_IMM64 (\r
+        FixupVal,\r
+        ((UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X),\r
+        IMM64_IMM7B_SIZE_X,\r
+        IMM64_IMM7B_INST_WORD_POS_X,\r
+        IMM64_IMM7B_VAL_POS_X\r
+        );\r
+\r
+      INS_IMM64 (\r
+        FixupVal,\r
+        ((UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X),\r
+        IMM64_IMM9D_SIZE_X,\r
+        IMM64_IMM9D_INST_WORD_POS_X,\r
+        IMM64_IMM9D_VAL_POS_X\r
+        );\r
+\r
+      INS_IMM64 (\r
+        FixupVal,\r
+        ((UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X),\r
+        IMM64_IMM5C_SIZE_X,\r
+        IMM64_IMM5C_INST_WORD_POS_X,\r
+        IMM64_IMM5C_VAL_POS_X\r
+        );\r
+\r
+      INS_IMM64 (\r
+        FixupVal,\r
+        ((UINT32 *) Fixup + IMM64_IC_INST_WORD_X),\r
+        IMM64_IC_SIZE_X,\r
+        IMM64_IC_INST_WORD_POS_X,\r
+        IMM64_IC_VAL_POS_X\r
+        );\r
+\r
+      INS_IMM64 (\r
+        FixupVal,\r
+        ((UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X),\r
+        IMM64_IMM41a_SIZE_X,\r
+        IMM64_IMM41a_INST_WORD_POS_X,\r
+        IMM64_IMM41a_VAL_POS_X\r
+        );\r
+\r
+      INS_IMM64 (\r
+        FixupVal,\r
+        ((UINT32 *) Fixup + IMM64_IMM41b_INST_WORD_X),\r
+        IMM64_IMM41b_SIZE_X,\r
+        IMM64_IMM41b_INST_WORD_POS_X,\r
+        IMM64_IMM41b_VAL_POS_X\r
+        );\r
+\r
+      INS_IMM64 (\r
+        FixupVal,\r
+        ((UINT32 *) Fixup + IMM64_IMM41c_INST_WORD_X),\r
+        IMM64_IMM41c_SIZE_X,\r
+        IMM64_IMM41c_INST_WORD_POS_X,\r
+        IMM64_IMM41c_VAL_POS_X\r
+        );\r
+\r
+      INS_IMM64 (\r
+        FixupVal,\r
+        ((UINT32 *) Fixup + IMM64_SIGN_INST_WORD_X),\r
+        IMM64_SIGN_SIZE_X,\r
+        IMM64_SIGN_INST_WORD_POS_X,\r
+        IMM64_SIGN_VAL_POS_X\r
+        );\r
+\r
+      *(UINT64 *) (*FixupData) = *F64;\r
+    }\r
+\r
+    *FixupData = *FixupData + sizeof (UINT64);\r
+    break;\r
+\r
+  default:\r
+    DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n"));\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+\r
+\r