diff --git a/BaseTools/Source/C/Common/BasePeCoff.c b/BaseTools/Source/C/Common/BasePeCoff.c index e7566b383b..62fbb2985c 100644 --- a/BaseTools/Source/C/Common/BasePeCoff.c +++ b/BaseTools/Source/C/Common/BasePeCoff.c @@ -4,6 +4,7 @@ Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -59,6 +60,14 @@ PeCoffLoaderRelocateArmImage ( IN UINT64 Adjust ); +RETURN_STATUS +PeCoffLoaderRelocateRiscVImage ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ); + STATIC RETURN_STATUS PeCoffLoaderGetPeHeader ( @@ -174,7 +183,8 @@ Returns: ImageContext->Machine != EFI_IMAGE_MACHINE_X64 && \ ImageContext->Machine != EFI_IMAGE_MACHINE_ARMT && \ ImageContext->Machine != EFI_IMAGE_MACHINE_EBC && \ - ImageContext->Machine != EFI_IMAGE_MACHINE_AARCH64) { + ImageContext->Machine != EFI_IMAGE_MACHINE_AARCH64 && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_RISCV64) { if (ImageContext->Machine == IMAGE_FILE_MACHINE_ARM) { // // There are two types of ARM images. Pure ARM and ARM/Thumb. @@ -802,6 +812,9 @@ Returns: case EFI_IMAGE_MACHINE_ARMT: Status = PeCoffLoaderRelocateArmImage (&Reloc, Fixup, &FixupData, Adjust); break; + case EFI_IMAGE_MACHINE_RISCV64: + Status = PeCoffLoaderRelocateRiscVImage (Reloc, Fixup, &FixupData, Adjust); + break; default: Status = RETURN_UNSUPPORTED; break; diff --git a/BaseTools/Source/C/Common/PeCoffLib.h b/BaseTools/Source/C/Common/PeCoffLib.h index 2fb2265e80..dd38f442f9 100644 --- a/BaseTools/Source/C/Common/PeCoffLib.h +++ b/BaseTools/Source/C/Common/PeCoffLib.h @@ -2,6 +2,7 @@ Function prototypes and defines on Memory Only PE COFF loader Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portion Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -25,6 +26,14 @@ #define IMAGE_ERROR_FAILED_RELOCATION 9 #define IMAGE_ERROR_FAILED_ICACHE_FLUSH 10 +// +// Macro definitions for RISC-V architecture. +// +#define RV_X(x, s, n) (((x) >> (s)) & ((1<<(n))-1)) +#define RISCV_IMM_BITS 12 +#define RISCV_IMM_REACH (1LL< Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent --*/ @@ -61,6 +62,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define IMM64_SIGN_INST_WORD_POS_X 27 #define IMM64_SIGN_VAL_POS_X 63 +UINT32 *RiscVHi20Fixup = NULL; + RETURN_STATUS PeCoffLoaderRelocateIa32Image ( IN UINT16 *Reloc, @@ -93,6 +96,89 @@ Returns: return RETURN_UNSUPPORTED; } +/*++ + +Routine Description: + + Performs an RISC-V specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + Status code + +--*/ +RETURN_STATUS +PeCoffLoaderRelocateRiscVImage ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + UINT32 Value; + UINT32 Value2; + UINT32 OrgValue; + + OrgValue = *(UINT32 *) Fixup; + OrgValue = OrgValue; + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_RISCV_HI20: + RiscVHi20Fixup = (UINT32 *) Fixup; + break; + + case EFI_IMAGE_REL_BASED_RISCV_LOW12I: + if (RiscVHi20Fixup != NULL) { + Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 20, 12)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value += (UINT32)Adjust; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12)); + *(UINT32 *)Fixup = (RV_X (Value, 0, 12) << 20) | \ + (RV_X (*(UINT32 *)Fixup, 0, 20)); + } + RiscVHi20Fixup = NULL; + break; + + case EFI_IMAGE_REL_BASED_RISCV_LOW12S: + if (RiscVHi20Fixup != NULL) { + Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 7, 5) | (RV_X(*(UINT32 *)Fixup, 25, 7) << 5)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value += (UINT32)Adjust; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12)); + Value2 = *(UINT32 *)Fixup & 0x01fff07f; + Value &= RISCV_IMM_REACH - 1; + *(UINT32 *)Fixup = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25))); + } + RiscVHi20Fixup = NULL; + break; + + default: + return EFI_UNSUPPORTED; + + } + return RETURN_SUCCESS; +} /** Pass in a pointer to an ARM MOVT or MOVW immediate instruction and diff --git a/BaseTools/Source/C/GenFv/GenFvInternalLib.c b/BaseTools/Source/C/GenFv/GenFvInternalLib.c index daebfe894c..d29a891c9c 100644 --- a/BaseTools/Source/C/GenFv/GenFvInternalLib.c +++ b/BaseTools/Source/C/GenFv/GenFvInternalLib.c @@ -4,6 +4,7 @@ This file contains the internal functions required to generate a Firmware Volume Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
Portions Copyright (c) 2016 HP Development Company, L.P.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -37,6 +38,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define ARM64_UNCONDITIONAL_JUMP_INSTRUCTION 0x14000000 BOOLEAN mArm = FALSE; +BOOLEAN mRiscV = FALSE; STATIC UINT32 MaxFfsAlignment = 0; BOOLEAN VtfFileFlag = FALSE; @@ -2291,6 +2293,104 @@ Returns: return EFI_SUCCESS; } +EFI_STATUS +UpdateRiscvResetVectorIfNeeded ( + MEMORY_FILE *FvImage, + FV_INFO *FvInfo + ) +/*++ + +Routine Description: + This parses the FV looking for SEC and patches that address into the + beginning of the FV header. + + For RISC-V ISA, the reset vector is at 0xfff~ff00h or 200h + +Arguments: + FvImage Memory file for the FV memory image/ + FvInfo Information read from INF file. + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_NOT_FOUND PEI Core file not found. + +--*/ +{ + EFI_STATUS Status; + UINT16 MachineType; + EFI_FILE_SECTION_POINTER SecPe32; + EFI_PHYSICAL_ADDRESS SecCoreEntryAddress; + + UINT32 bSecCore; + UINT32 tmp; + + + // + // Verify input parameters + // + if (FvImage == NULL || FvInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize FV library + // + InitializeFvLib (FvImage->FileImage, FvInfo->Size); + + // + // Find the Sec Core + // + Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32); + if(EFI_ERROR(Status)) { + printf("skip because Secutiry Core not found\n"); + return EFI_SUCCESS; + } + + DebugMsg (NULL, 0, 9, "Update SEC core in FV Header", NULL); + + Status = GetCoreMachineType(SecPe32, &MachineType); + if(EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC core."); + return EFI_ABORTED; + } + + if (MachineType != EFI_IMAGE_MACHINE_RISCV64) { + Error(NULL, 0, 3000, "Invalid", "Could not update SEC core because Machine type is not RiscV."); + return EFI_ABORTED; + } + + Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress); + if(EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core."); + return EFI_ABORTED; + } + + VerboseMsg("SecCore entry point Address = 0x%llX", (unsigned long long) SecCoreEntryAddress); + VerboseMsg("BaseAddress = 0x%llX", (unsigned long long) FvInfo->BaseAddress); + bSecCore = (UINT32)(SecCoreEntryAddress - FvInfo->BaseAddress); + VerboseMsg("offset = 0x%llX", bSecCore); + + if(bSecCore > 0x0fffff) { + Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 1MB of start of the FV"); + return EFI_ABORTED; + } + + tmp = bSecCore; + bSecCore = 0; + //J-type + bSecCore = (tmp&0x100000)<<11; //imm[20] at bit[31] + bSecCore |= (tmp&0x0007FE)<<20; //imm[10:1] at bit[30:21] + bSecCore |= (tmp&0x000800)<<9; //imm[11] at bit[20] + bSecCore |= (tmp&0x0FF000); //imm[19:12] at bit[19:12] + bSecCore |= 0x6F; //JAL opcode + + memcpy(FvImage->FileImage, &bSecCore, sizeof(bSecCore)); + + return EFI_SUCCESS; +} + EFI_STATUS GetPe32Info ( IN UINT8 *Pe32, @@ -2383,7 +2483,8 @@ Returns: // Verify machine type is supported // if ((*MachineType != EFI_IMAGE_MACHINE_IA32) && (*MachineType != EFI_IMAGE_MACHINE_X64) && (*MachineType != EFI_IMAGE_MACHINE_EBC) && - (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64)) { + (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64) && + (*MachineType != EFI_IMAGE_MACHINE_RISCV64)) { Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file."); return EFI_UNSUPPORTED; } @@ -2826,7 +2927,8 @@ Returns: Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add pad file between the last file and the VTF file."); goto Finish; } - if (!mArm) { + + if (!mArm && !mRiscV) { // // Update reset vector (SALE_ENTRY for IPF) // Now for IA32 and IA64 platform, the fv which has bsf file must have the @@ -2861,6 +2963,22 @@ Returns: FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); } + if (mRiscV) { + // + // Update RISCV reset vector. + // + Status = UpdateRiscvResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector for RISC-V."); + goto Finish; + } + // + // Update Checksum for FvHeader + // + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + } + // // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV // @@ -3448,6 +3566,10 @@ Returns: mArm = TRUE; } + if (ImageContext.Machine == EFI_IMAGE_MACHINE_RISCV64) { + mRiscV = TRUE; + } + // // Keep Image Context for PE image in FV // @@ -3601,7 +3723,7 @@ Returns: ImageContext.DestinationAddress = NewPe32BaseAddress; Status = PeCoffLoaderRelocateImage (&ImageContext); if (EFI_ERROR (Status)) { - Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName); + Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s Status=%d", FileName, Status); free ((VOID *) MemoryImagePointer); return Status; } diff --git a/BaseTools/Source/C/GenFw/Elf32Convert.c b/BaseTools/Source/C/GenFw/Elf32Convert.c index 46089ff370..7f351287a9 100644 --- a/BaseTools/Source/C/GenFw/Elf32Convert.c +++ b/BaseTools/Source/C/GenFw/Elf32Convert.c @@ -3,6 +3,7 @@ Elf32 Convert solution Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
Portions copyright (c) 2013, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -141,8 +142,8 @@ InitializeElf32 ( Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN"); return FALSE; } - if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM))) { - Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM"); + if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM) || (mEhdr->e_machine == EM_RISCV))) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf32 machine."); return FALSE; } if (mEhdr->e_version != EV_CURRENT) { diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c index d623dce1f9..4ed6b4477e 100644 --- a/BaseTools/Source/C/GenFw/Elf64Convert.c +++ b/BaseTools/Source/C/GenFw/Elf64Convert.c @@ -3,6 +3,7 @@ Elf64 convert solution Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -122,6 +123,13 @@ STATIC UINT32 mHiiRsrcOffset; STATIC UINT32 mRelocOffset; STATIC UINT32 mDebugOffset; +// +// Used for RISC-V relocations. +// +STATIC UINT8 *mRiscVPass1Targ = NULL; +STATIC Elf_Shdr *mRiscVPass1Sym = NULL; +STATIC Elf64_Half mRiscVPass1SymSecIndex = 0; + // // Initialization Function // @@ -153,8 +161,8 @@ InitializeElf64 ( Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN"); return FALSE; } - if (!((mEhdr->e_machine == EM_X86_64) || (mEhdr->e_machine == EM_AARCH64))) { - Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_X86_64 or EM_AARCH64"); + if (!((mEhdr->e_machine == EM_X86_64) || (mEhdr->e_machine == EM_AARCH64) || (mEhdr->e_machine == EM_RISCV64))) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf64 machine."); return FALSE; } if (mEhdr->e_version != EV_CURRENT) { @@ -452,6 +460,147 @@ EmitGOTRelocations ( mGOTMaxCoffEntries = 0; mGOTNumCoffEntries = 0; } +// +// RISC-V 64 specific Elf WriteSection function. +// +STATIC +VOID +WriteSectionRiscV64 ( + Elf_Rela *Rel, + UINT8 *Targ, + Elf_Shdr *SymShdr, + Elf_Sym *Sym + ) +{ + UINT32 Value; + UINT32 Value2; + + switch (ELF_R_TYPE(Rel->r_info)) { + case R_RISCV_NONE: + break; + + case R_RISCV_32: + *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); + break; + + case R_RISCV_64: + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + break; + + case R_RISCV_HI20: + mRiscVPass1Targ = Targ; + mRiscVPass1Sym = SymShdr; + mRiscVPass1SymSecIndex = Sym->st_shndx; + break; + + case R_RISCV_LO12_I: + if (mRiscVPass1Sym == SymShdr && mRiscVPass1Targ != NULL && mRiscVPass1SymSecIndex == Sym->st_shndx && mRiscVPass1SymSecIndex != 0) { + Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value = Value - (UINT32)SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)mRiscVPass1Targ = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)mRiscVPass1Targ, 0, 12)); + *(UINT32 *)Targ = (RV_X (Value, 0, 12) << 20) | \ + (RV_X (*(UINT32 *)Targ, 0, 20)); + } + mRiscVPass1Sym = NULL; + mRiscVPass1Targ = NULL; + mRiscVPass1SymSecIndex = 0; + break; + + case R_RISCV_LO12_S: + if (mRiscVPass1Sym == SymShdr && mRiscVPass1Targ != NULL && mRiscVPass1SymSecIndex == Sym->st_shndx && mRiscVPass1SymSecIndex != 0) { + Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Targ, 7, 5) | (RV_X(*(UINT32 *)Targ, 25, 7) << 5)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value = Value - (UINT32)SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)mRiscVPass1Targ = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)mRiscVPass1Targ, 0, 12)); + Value2 = *(UINT32 *)Targ & 0x01fff07f; + Value &= RISCV_IMM_REACH - 1; + *(UINT32 *)Targ = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25))); + } + mRiscVPass1Sym = NULL; + mRiscVPass1Targ = NULL; + mRiscVPass1SymSecIndex = 0; + break; + + case R_RISCV_PCREL_HI20: + mRiscVPass1Targ = Targ; + mRiscVPass1Sym = SymShdr; + mRiscVPass1SymSecIndex = Sym->st_shndx; + + Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20)); + break; + + case R_RISCV_PCREL_LO12_I: + if (mRiscVPass1Targ != NULL && mRiscVPass1Sym != NULL && mRiscVPass1SymSecIndex != 0) { + int i; + Value2 = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20)); + Value = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12)); + if(Value & (RISCV_IMM_REACH/2)) { + Value |= ~(RISCV_IMM_REACH-1); + } + Value = Value - (UINT32)mRiscVPass1Sym->sh_addr + mCoffSectionsOffset[mRiscVPass1SymSecIndex]; + if(-2048 > (INT32)Value) { + i = (((INT32)Value * -1) / 4096); + Value2 -= i; + Value += 4096 * i; + if(-2048 > (INT32)Value) { + Value2 -= 1; + Value += 4096; + } + } + else if( 2047 < (INT32)Value) { + i = (Value / 4096); + Value2 += i; + Value -= 4096 * i; + if(2047 < (INT32)Value) { + Value2 += 1; + Value -= 4096; + } + } + + *(UINT32 *)Targ = (RV_X(Value, 0, 12) << 20) | (RV_X(*(UINT32*)Targ, 0, 20)); + *(UINT32 *)mRiscVPass1Targ = (RV_X(Value2, 0, 20)<<12) | (RV_X(*(UINT32 *)mRiscVPass1Targ, 0, 12)); + } + mRiscVPass1Sym = NULL; + mRiscVPass1Targ = NULL; + mRiscVPass1SymSecIndex = 0; + break; + + case R_RISCV_ADD64: + case R_RISCV_SUB64: + case R_RISCV_ADD32: + case R_RISCV_SUB32: + case R_RISCV_BRANCH: + case R_RISCV_JAL: + case R_RISCV_GPREL_I: + case R_RISCV_GPREL_S: + case R_RISCV_CALL: + case R_RISCV_RVC_BRANCH: + case R_RISCV_RVC_JUMP: + case R_RISCV_RELAX: + case R_RISCV_SUB6: + case R_RISCV_SET6: + case R_RISCV_SET8: + case R_RISCV_SET16: + case R_RISCV_SET32: + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_RISCV64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } +} // // Elf functions interface implementation @@ -481,6 +630,7 @@ ScanSections64 ( switch (mEhdr->e_machine) { case EM_X86_64: case EM_AARCH64: + case EM_RISCV64: mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64); break; default: @@ -690,6 +840,11 @@ ScanSections64 ( NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_AARCH64; NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; break; + case EM_RISCV64: + NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_RISCV64; + NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + default: VerboseMsg ("%s unknown e_machine type. Assume X64", (UINTN)mEhdr->e_machine); NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64; @@ -894,12 +1049,18 @@ WriteSections64 ( SymName = (const UINT8 *)""; } - Error (NULL, 0, 3000, "Invalid", - "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type. " - "For example, absolute and undefined symbols are not supported.", - mInImageName, SymName, Sym->st_value); + // + // Skip error on EM_RISCV64 becasue no symble name is built + // from RISC-V toolchain. + // + if (mEhdr->e_machine != EM_RISCV64) { + Error (NULL, 0, 3000, "Invalid", + "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type. " + "For example, absolute and undefined symbols are not supported.", + mInImageName, SymName, Sym->st_value); - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); + } } SymShdr = GetShdrByIndex(Sym->st_shndx); @@ -1151,6 +1312,11 @@ WriteSections64 ( default: Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); } + } else if (mEhdr->e_machine == EM_RISCV64) { + // + // Write section for RISC-V 64 architecture. + // + WriteSectionRiscV64 (Rel, Targ, SymShdr, Sym); } else { Error (NULL, 0, 3000, "Invalid", "Not a supported machine type"); } @@ -1170,6 +1336,7 @@ WriteRelocations64 ( UINT32 Index; EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; EFI_IMAGE_DATA_DIRECTORY *Dir; + UINT32 RiscVRelType; for (Index = 0; Index < mEhdr->e_shnum; Index++) { Elf_Shdr *RelShdr = GetShdrByIndex(Index); @@ -1276,6 +1443,107 @@ WriteRelocations64 ( default: Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); } + } else if (mEhdr->e_machine == EM_RISCV64) { + RiscVRelType = ELF_R_TYPE(Rel->r_info); + switch (RiscVRelType) { + case R_RISCV_NONE: + break; + + case R_RISCV_32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + + case R_RISCV_64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_DIR64); + break; + + case R_RISCV_HI20: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_RISCV_HI20); + break; + + case R_RISCV_LO12_I: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_RISCV_LOW12I); + break; + + case R_RISCV_LO12_S: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_RISCV_LOW12S); + break; + + case R_RISCV_ADD64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_SUB64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_ADD32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_SUB32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_BRANCH: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_JAL: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_GPREL_I: + case R_RISCV_GPREL_S: + case R_RISCV_CALL: + case R_RISCV_RVC_BRANCH: + case R_RISCV_RVC_JUMP: + case R_RISCV_RELAX: + case R_RISCV_SUB6: + case R_RISCV_SET6: + case R_RISCV_SET8: + case R_RISCV_SET16: + case R_RISCV_SET32: + case R_RISCV_PCREL_HI20: + case R_RISCV_PCREL_LO12_I: + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_RISCV64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } } else { Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine); } diff --git a/BaseTools/Source/C/GenFw/elf_common.h b/BaseTools/Source/C/GenFw/elf_common.h index 15c9e33d3f..b67f59e7a0 100644 --- a/BaseTools/Source/C/GenFw/elf_common.h +++ b/BaseTools/Source/C/GenFw/elf_common.h @@ -3,6 +3,7 @@ Ported ELF include files from FreeBSD Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+Portion Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -178,6 +179,8 @@ typedef struct { #define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ #define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ #define EM_AARCH64 183 /* ARM 64bit Architecture */ +#define EM_RISCV64 243 /* 64bit RISC-V Architecture */ +#define EM_RISCV 244 /* 32bit RISC-V Architecture */ /* Non-standard or deprecated. */ #define EM_486 6 /* Intel i486. */ @@ -979,5 +982,64 @@ typedef struct { #define R_X86_64_GOTPCRELX 41 /* Load from 32 bit signed pc relative offset to GOT entry without REX prefix, relaxable. */ #define R_X86_64_REX_GOTPCRELX 42 /* Load from 32 bit signed pc relative offset to GOT entry with REX prefix, relaxable. */ +/* + * RISC-V relocation types + */ +/* Relocation types used by the dynamic linker */ +#define R_RISCV_NONE 0 +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_RELATIVE 3 +#define R_RISCV_COPY 4 +#define R_RISCV_JUMP_SLOT 5 +#define R_RISCV_TLS_DTPMOD32 6 +#define R_RISCV_TLS_DTPMOD64 7 +#define R_RISCV_TLS_DTPREL32 8 +#define R_RISCV_TLS_DTPREL64 9 +#define R_RISCV_TLS_TPREL32 10 +#define R_RISCV_TLS_TPREL64 11 + +/* Relocation types not used by the dynamic linker */ +#define R_RISCV_BRANCH 16 +#define R_RISCV_JAL 17 +#define R_RISCV_CALL 18 +#define R_RISCV_CALL_PLT 19 +#define R_RISCV_GOT_HI20 20 +#define R_RISCV_TLS_GOT_HI20 21 +#define R_RISCV_TLS_GD_HI20 22 +#define R_RISCV_PCREL_HI20 23 +#define R_RISCV_PCREL_LO12_I 24 +#define R_RISCV_PCREL_LO12_S 25 +#define R_RISCV_HI20 26 +#define R_RISCV_LO12_I 27 +#define R_RISCV_LO12_S 28 +#define R_RISCV_TPREL_HI20 29 +#define R_RISCV_TPREL_LO12_I 30 +#define R_RISCV_TPREL_LO12_S 31 +#define R_RISCV_TPREL_ADD 32 +#define R_RISCV_ADD8 33 +#define R_RISCV_ADD16 34 +#define R_RISCV_ADD32 35 +#define R_RISCV_ADD64 36 +#define R_RISCV_SUB8 37 +#define R_RISCV_SUB16 38 +#define R_RISCV_SUB32 39 +#define R_RISCV_SUB64 40 +#define R_RISCV_GNU_VTINHERIT 41 +#define R_RISCV_GNU_VTENTRY 42 +#define R_RISCV_ALIGN 43 +#define R_RISCV_RVC_BRANCH 44 +#define R_RISCV_RVC_JUMP 45 +#define R_RISCV_RVC_LUI 46 +#define R_RISCV_GPREL_I 47 +#define R_RISCV_GPREL_S 48 +#define R_RISCV_TPREL_I 49 +#define R_RISCV_TPREL_S 50 +#define R_RISCV_RELAX 51 +#define R_RISCV_SUB6 52 +#define R_RISCV_SET6 53 +#define R_RISCV_SET8 54 +#define R_RISCV_SET16 55 +#define R_RISCV_SET32 56 #endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h index 44037d13f3..f17b8ee19b 100644 --- a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h +++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h @@ -6,6 +6,7 @@ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+ Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -41,6 +42,7 @@ #define IMAGE_FILE_MACHINE_ARM 0x01c0 // Thumb only #define IMAGE_FILE_MACHINE_ARMT 0x01c2 // 32bit Mixed ARM and Thumb/Thumb 2 Little Endian #define IMAGE_FILE_MACHINE_ARM64 0xAA64 // 64bit ARM Architecture, Little Endian +#define IMAGE_FILE_MACHINE_RISCV64 0x5064 // 64bit RISC-V ISA // // Support old names for backward compatible @@ -50,6 +52,7 @@ #define EFI_IMAGE_MACHINE_X64 IMAGE_FILE_MACHINE_X64 #define EFI_IMAGE_MACHINE_ARMT IMAGE_FILE_MACHINE_ARMT #define EFI_IMAGE_MACHINE_AARCH64 IMAGE_FILE_MACHINE_ARM64 +#define EFI_IMAGE_MACHINE_RISCV64 IMAGE_FILE_MACHINE_RISCV64 #define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ #define EFI_IMAGE_OS2_SIGNATURE 0x454E // NE @@ -504,7 +507,10 @@ typedef struct { #define EFI_IMAGE_REL_BASED_HIGHADJ 4 #define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5 #define EFI_IMAGE_REL_BASED_ARM_MOV32A 5 +#define EFI_IMAGE_REL_BASED_RISCV_HI20 5 #define EFI_IMAGE_REL_BASED_ARM_MOV32T 7 +#define EFI_IMAGE_REL_BASED_RISCV_LOW12I 7 +#define EFI_IMAGE_REL_BASED_RISCV_LOW12S 8 #define EFI_IMAGE_REL_BASED_IA64_IMM64 9 #define EFI_IMAGE_REL_BASED_DIR64 10