\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
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
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
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
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
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
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
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
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
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