]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/GenFw/Elf64Convert.c
BaseTools: BaseTools changes for RISC-V platform.
[mirror_edk2.git] / BaseTools / Source / C / GenFw / Elf64Convert.c
index d623dce1f9da020f110de1dd14d1182e9f90818a..4ed6b4477ea9310a488c5f58a3927c03b315ed78 100644 (file)
@@ -3,6 +3,7 @@ Elf64 convert solution
 \r
 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
 Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>\r
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>\r
 \r
 SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
@@ -122,6 +123,13 @@ STATIC UINT32 mHiiRsrcOffset;
 STATIC UINT32 mRelocOffset;\r
 STATIC UINT32 mDebugOffset;\r
 \r
+//\r
+// Used for RISC-V relocations.\r
+//\r
+STATIC UINT8       *mRiscVPass1Targ = NULL;\r
+STATIC Elf_Shdr    *mRiscVPass1Sym = NULL;\r
+STATIC Elf64_Half  mRiscVPass1SymSecIndex = 0;\r
+\r
 //\r
 // Initialization Function\r
 //\r
@@ -153,8 +161,8 @@ InitializeElf64 (
     Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");\r
     return FALSE;\r
   }\r
-  if (!((mEhdr->e_machine == EM_X86_64) || (mEhdr->e_machine == EM_AARCH64))) {\r
-    Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_X86_64 or EM_AARCH64");\r
+  if (!((mEhdr->e_machine == EM_X86_64) || (mEhdr->e_machine == EM_AARCH64) || (mEhdr->e_machine == EM_RISCV64))) {\r
+    Error (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf64 machine.");\r
     return FALSE;\r
   }\r
   if (mEhdr->e_version != EV_CURRENT) {\r
@@ -452,6 +460,147 @@ EmitGOTRelocations (
   mGOTMaxCoffEntries = 0;\r
   mGOTNumCoffEntries = 0;\r
 }\r
+//\r
+// RISC-V 64 specific Elf WriteSection function.\r
+//\r
+STATIC\r
+VOID\r
+WriteSectionRiscV64 (\r
+  Elf_Rela  *Rel,\r
+  UINT8     *Targ,\r
+  Elf_Shdr  *SymShdr,\r
+  Elf_Sym   *Sym\r
+  )\r
+{\r
+  UINT32      Value;\r
+  UINT32      Value2;\r
+\r
+  switch (ELF_R_TYPE(Rel->r_info)) {\r
+  case R_RISCV_NONE:\r
+    break;\r
+\r
+  case R_RISCV_32:\r
+    *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]);\r
+    break;\r
+\r
+  case R_RISCV_64:\r
+    *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
+    break;\r
+\r
+  case R_RISCV_HI20:\r
+    mRiscVPass1Targ = Targ;\r
+    mRiscVPass1Sym = SymShdr;\r
+    mRiscVPass1SymSecIndex = Sym->st_shndx;\r
+    break;\r
+\r
+  case R_RISCV_LO12_I:\r
+    if (mRiscVPass1Sym == SymShdr && mRiscVPass1Targ != NULL && mRiscVPass1SymSecIndex == Sym->st_shndx && mRiscVPass1SymSecIndex != 0) {\r
+      Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20) << 12);\r
+      Value2 = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12));\r
+      if (Value2 & (RISCV_IMM_REACH/2)) {\r
+        Value2 |= ~(RISCV_IMM_REACH-1);\r
+      }\r
+      Value += Value2;\r
+      Value = Value - (UINT32)SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
+      Value2 = RISCV_CONST_HIGH_PART (Value);\r
+      *(UINT32 *)mRiscVPass1Targ = (RV_X (Value2, 12, 20) << 12) | \\r
+                             (RV_X (*(UINT32 *)mRiscVPass1Targ, 0, 12));\r
+      *(UINT32 *)Targ = (RV_X (Value, 0, 12) << 20) | \\r
+                        (RV_X (*(UINT32 *)Targ, 0, 20));\r
+    }\r
+    mRiscVPass1Sym = NULL;\r
+    mRiscVPass1Targ = NULL;\r
+    mRiscVPass1SymSecIndex = 0;\r
+    break;\r
+\r
+  case R_RISCV_LO12_S:\r
+    if (mRiscVPass1Sym == SymShdr && mRiscVPass1Targ != NULL && mRiscVPass1SymSecIndex == Sym->st_shndx && mRiscVPass1SymSecIndex != 0) {\r
+      Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20) << 12);\r
+      Value2 = (UINT32)(RV_X(*(UINT32 *)Targ, 7, 5) | (RV_X(*(UINT32 *)Targ, 25, 7) << 5));\r
+      if (Value2 & (RISCV_IMM_REACH/2)) {\r
+        Value2 |= ~(RISCV_IMM_REACH-1);\r
+      }\r
+      Value += Value2;\r
+      Value = Value - (UINT32)SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];\r
+      Value2 = RISCV_CONST_HIGH_PART (Value);\r
+      *(UINT32 *)mRiscVPass1Targ = (RV_X (Value2, 12, 20) << 12) | \\r
+                                 (RV_X (*(UINT32 *)mRiscVPass1Targ, 0, 12));\r
+      Value2 = *(UINT32 *)Targ & 0x01fff07f;\r
+      Value &= RISCV_IMM_REACH - 1;\r
+      *(UINT32 *)Targ = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25)));\r
+    }\r
+    mRiscVPass1Sym = NULL;\r
+    mRiscVPass1Targ = NULL;\r
+    mRiscVPass1SymSecIndex = 0;\r
+    break;\r
+\r
+  case R_RISCV_PCREL_HI20:\r
+    mRiscVPass1Targ = Targ;\r
+    mRiscVPass1Sym = SymShdr;\r
+    mRiscVPass1SymSecIndex = Sym->st_shndx;\r
+\r
+    Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20));\r
+    break;\r
+\r
+  case R_RISCV_PCREL_LO12_I:\r
+    if (mRiscVPass1Targ != NULL && mRiscVPass1Sym != NULL && mRiscVPass1SymSecIndex != 0) {\r
+      int i;\r
+      Value2 = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20));\r
+      Value = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12));\r
+      if(Value & (RISCV_IMM_REACH/2)) {\r
+        Value |= ~(RISCV_IMM_REACH-1);\r
+      }\r
+      Value = Value - (UINT32)mRiscVPass1Sym->sh_addr + mCoffSectionsOffset[mRiscVPass1SymSecIndex];\r
+      if(-2048 > (INT32)Value) {\r
+        i = (((INT32)Value * -1) / 4096);\r
+        Value2 -= i;\r
+        Value += 4096 * i;\r
+        if(-2048 > (INT32)Value) {\r
+          Value2 -= 1;\r
+          Value += 4096;\r
+        }\r
+      }\r
+      else if( 2047 < (INT32)Value) {\r
+        i = (Value / 4096);\r
+        Value2 += i;\r
+        Value -= 4096 * i;\r
+        if(2047 < (INT32)Value) {\r
+          Value2 += 1;\r
+          Value -= 4096;\r
+        }\r
+      }\r
+\r
+      *(UINT32 *)Targ = (RV_X(Value, 0, 12) << 20) | (RV_X(*(UINT32*)Targ, 0, 20));\r
+      *(UINT32 *)mRiscVPass1Targ = (RV_X(Value2, 0, 20)<<12) | (RV_X(*(UINT32 *)mRiscVPass1Targ, 0, 12));\r
+    }\r
+    mRiscVPass1Sym = NULL;\r
+    mRiscVPass1Targ = NULL;\r
+    mRiscVPass1SymSecIndex = 0;\r
+    break;\r
+\r
+  case R_RISCV_ADD64:\r
+  case R_RISCV_SUB64:\r
+  case R_RISCV_ADD32:\r
+  case R_RISCV_SUB32:\r
+  case R_RISCV_BRANCH:\r
+  case R_RISCV_JAL:\r
+  case R_RISCV_GPREL_I:\r
+  case R_RISCV_GPREL_S:\r
+  case R_RISCV_CALL:\r
+  case R_RISCV_RVC_BRANCH:\r
+  case R_RISCV_RVC_JUMP:\r
+  case R_RISCV_RELAX:\r
+  case R_RISCV_SUB6:\r
+  case R_RISCV_SET6:\r
+  case R_RISCV_SET8:\r
+  case R_RISCV_SET16:\r
+  case R_RISCV_SET32:\r
+    break;\r
+\r
+  default:\r
+    Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_RISCV64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
+  }\r
+}\r
 \r
 //\r
 // Elf functions interface implementation\r
@@ -481,6 +630,7 @@ ScanSections64 (
   switch (mEhdr->e_machine) {\r
   case EM_X86_64:\r
   case EM_AARCH64:\r
+  case EM_RISCV64:\r
     mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64);\r
   break;\r
   default:\r
@@ -690,6 +840,11 @@ ScanSections64 (
     NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_AARCH64;\r
     NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
     break;\r
+  case EM_RISCV64:\r
+    NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_RISCV64;\r
+    NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+    break;\r
+\r
   default:\r
     VerboseMsg ("%s unknown e_machine type. Assume X64", (UINTN)mEhdr->e_machine);\r
     NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;\r
@@ -894,12 +1049,18 @@ WriteSections64 (
             SymName = (const UINT8 *)"<unknown>";\r
           }\r
 \r
-          Error (NULL, 0, 3000, "Invalid",\r
-                 "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type.  "\r
-                 "For example, absolute and undefined symbols are not supported.",\r
-                 mInImageName, SymName, Sym->st_value);\r
+          //\r
+          // Skip error on EM_RISCV64 becasue no symble name is built\r
+          // from RISC-V toolchain.\r
+          //\r
+          if (mEhdr->e_machine != EM_RISCV64) {\r
+            Error (NULL, 0, 3000, "Invalid",\r
+                   "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type.  "\r
+                   "For example, absolute and undefined symbols are not supported.",\r
+                   mInImageName, SymName, Sym->st_value);\r
 \r
-          exit(EXIT_FAILURE);\r
+            exit(EXIT_FAILURE);\r
+          }\r
         }\r
         SymShdr = GetShdrByIndex(Sym->st_shndx);\r
 \r
@@ -1151,6 +1312,11 @@ WriteSections64 (
           default:\r
             Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
           }\r
+        } else if (mEhdr->e_machine == EM_RISCV64) {\r
+          //\r
+          // Write section for RISC-V 64 architecture.\r
+          //\r
+          WriteSectionRiscV64 (Rel, Targ, SymShdr, Sym);\r
         } else {\r
           Error (NULL, 0, 3000, "Invalid", "Not a supported machine type");\r
         }\r
@@ -1170,6 +1336,7 @@ WriteRelocations64 (
   UINT32                           Index;\r
   EFI_IMAGE_OPTIONAL_HEADER_UNION  *NtHdr;\r
   EFI_IMAGE_DATA_DIRECTORY         *Dir;\r
+  UINT32 RiscVRelType;\r
 \r
   for (Index = 0; Index < mEhdr->e_shnum; Index++) {\r
     Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
@@ -1276,6 +1443,107 @@ WriteRelocations64 (
             default:\r
                 Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
             }\r
+          } else if (mEhdr->e_machine == EM_RISCV64) {\r
+            RiscVRelType = ELF_R_TYPE(Rel->r_info);\r
+            switch (RiscVRelType) {\r
+            case R_RISCV_NONE:\r
+              break;\r
+\r
+            case R_RISCV_32:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_HIGHLOW);\r
+              break;\r
+\r
+            case R_RISCV_64:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_DIR64);\r
+              break;\r
+\r
+            case R_RISCV_HI20:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_RISCV_HI20);\r
+              break;\r
+\r
+            case R_RISCV_LO12_I:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_RISCV_LOW12I);\r
+              break;\r
+\r
+            case R_RISCV_LO12_S:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_RISCV_LOW12S);\r
+              break;\r
+\r
+            case R_RISCV_ADD64:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_ABSOLUTE);\r
+              break;\r
+\r
+            case R_RISCV_SUB64:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_ABSOLUTE);\r
+              break;\r
+\r
+            case R_RISCV_ADD32:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_ABSOLUTE);\r
+              break;\r
+\r
+            case R_RISCV_SUB32:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_ABSOLUTE);\r
+              break;\r
+\r
+            case R_RISCV_BRANCH:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_ABSOLUTE);\r
+              break;\r
+\r
+            case R_RISCV_JAL:\r
+              CoffAddFixup(\r
+                (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]\r
+                + (Rel->r_offset - SecShdr->sh_addr)),\r
+                EFI_IMAGE_REL_BASED_ABSOLUTE);\r
+              break;\r
+\r
+            case R_RISCV_GPREL_I:\r
+            case R_RISCV_GPREL_S:\r
+            case R_RISCV_CALL:\r
+            case R_RISCV_RVC_BRANCH:\r
+            case R_RISCV_RVC_JUMP:\r
+            case R_RISCV_RELAX:\r
+            case R_RISCV_SUB6:\r
+            case R_RISCV_SET6:\r
+            case R_RISCV_SET8:\r
+            case R_RISCV_SET16:\r
+            case R_RISCV_SET32:\r
+            case R_RISCV_PCREL_HI20:\r
+            case R_RISCV_PCREL_LO12_I:\r
+              break;\r
+\r
+            default:\r
+              Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_RISCV64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
+            }\r
           } else {\r
             Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine);\r
           }\r