]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/Common/PeCoffLoaderEx.c
BaseTools: Update GenFw/GenFv to support LoongArch platform.
[mirror_edk2.git] / BaseTools / Source / C / Common / PeCoffLoaderEx.c
index 799f28297012ab85c1982542a6f98f974b84a6a0..2cc428d733b44bc830e59982cd463c97148c6eb4 100644 (file)
@@ -4,6 +4,7 @@ IA32 and X64 Specific relocation fixups
 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
 Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>\r
 Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>\r
+Copyright (c) 2022, Loongson Technology Corporation Limited. All rights reserved.<BR>\r
 SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 --*/\r
@@ -332,3 +333,81 @@ PeCoffLoaderRelocateArmImage (
 \r
   return RETURN_SUCCESS;\r
 }\r
+\r
+/**\r
+  Performs a LoongArch specific relocation fixup.\r
+\r
+  @param[in]       Reloc       Pointer to the relocation record.\r
+  @param[in, out]  Fixup       Pointer to the address to fix up.\r
+  @param[in, out]  FixupData   Pointer to a buffer to log the fixups.\r
+  @param[in]       Adjust      The offset to adjust the fixup.\r
+\r
+  @return Status code.\r
+**/\r
+RETURN_STATUS\r
+PeCoffLoaderRelocateLoongArch64Image (\r
+  IN UINT16     *Reloc,\r
+  IN OUT CHAR8  *Fixup,\r
+  IN OUT CHAR8  **FixupData,\r
+  IN UINT64     Adjust\r
+  )\r
+{\r
+  UINT8  RelocType;\r
+  UINT64 Value;\r
+  UINT64 Tmp1;\r
+  UINT64 Tmp2;\r
+\r
+  RelocType = ((*Reloc) >> 12);\r
+  Value     = 0;\r
+  Tmp1      = 0;\r
+  Tmp2      = 0;\r
+\r
+  switch (RelocType) {\r
+    case EFI_IMAGE_REL_BASED_LOONGARCH64_MARK_LA:\r
+      // The next four instructions are used to load a 64 bit address, relocate all of them\r
+      Value = (*(UINT32 *)Fixup & 0x1ffffe0) << 7 |       // lu12i.w 20bits from bit5\r
+              (*((UINT32 *)Fixup + 1) & 0x3ffc00) >> 10;  // ori     12bits from bit10\r
+      Tmp1   = *((UINT32 *)Fixup + 2) & 0x1ffffe0;        // lu32i.d 20bits from bit5\r
+      Tmp2   = *((UINT32 *)Fixup + 3) & 0x3ffc00;         // lu52i.d 12bits from bit10\r
+      Value  = Value | (Tmp1 << 27) | (Tmp2 << 42);\r
+      Value += Adjust;\r
+\r
+      *(UINT32 *)Fixup = (*(UINT32 *)Fixup & ~0x1ffffe0) | (((Value >> 12) & 0xfffff) << 5);\r
+      if (*FixupData != NULL) {\r
+        *FixupData              = ALIGN_POINTER (*FixupData, sizeof (UINT32));\r
+        *(UINT32 *)(*FixupData) = *(UINT32 *)Fixup;\r
+        *FixupData              = *FixupData + sizeof (UINT32);\r
+      }\r
+\r
+      Fixup           += sizeof (UINT32);\r
+      *(UINT32 *)Fixup = (*(UINT32 *)Fixup & ~0x3ffc00) | ((Value & 0xfff) << 10);\r
+      if (*FixupData != NULL) {\r
+        *FixupData              = ALIGN_POINTER (*FixupData, sizeof (UINT32));\r
+        *(UINT32 *)(*FixupData) = *(UINT32 *)Fixup;\r
+        *FixupData              = *FixupData + sizeof (UINT32);\r
+      }\r
+\r
+      Fixup           += sizeof (UINT32);\r
+      *(UINT32 *)Fixup = (*(UINT32 *)Fixup & ~0x1ffffe0) | (((Value >> 32) & 0xfffff) << 5);\r
+      if (*FixupData != NULL) {\r
+        *FixupData              = ALIGN_POINTER (*FixupData, sizeof (UINT32));\r
+        *(UINT32 *)(*FixupData) = *(UINT32 *)Fixup;\r
+        *FixupData              = *FixupData + sizeof (UINT32);\r
+      }\r
+\r
+      Fixup           += sizeof (UINT32);\r
+      *(UINT32 *)Fixup = (*(UINT32 *)Fixup & ~0x3ffc00) | (((Value >> 52) & 0xfff) << 10);\r
+      if (*FixupData != NULL) {\r
+        *FixupData              = ALIGN_POINTER (*FixupData, sizeof (UINT32));\r
+        *(UINT32 *)(*FixupData) = *(UINT32 *)Fixup;\r
+        *FixupData              = *FixupData + sizeof (UINT32);\r
+      }\r
+\r
+      break;\r
+    default:\r
+      Error (NULL, 0, 3000, "", "PeCoffLoaderRelocateLoongArch64Image: Fixup[0x%x] Adjust[0x%llx] *Reloc[0x%x], type[0x%x].", *(UINT32 *)Fixup, Adjust, *Reloc, RelocType);\r
+      return RETURN_UNSUPPORTED;\r
+  }\r
+\r
+  return RETURN_SUCCESS;\r
+}\r