BaseTools: BaseTools changes for RISC-V platform.

C code changes for building EDK2 RISC-V platform.

Signed-off-by: Abner Chang <abner.chang@hpe.com>
Co-authored-by: Gilbert Chen <gilbert.chen@hpe.com>
Co-authored-by: Daniel Helmut Schaefer <daniel.schaefer@hpe.com>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
Reviewed-by: Bob Feng <bob.c.feng@intel.com>

Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Gilbert Chen <gilbert.chen@hpe.com>
This commit is contained in:
Abner Chang 2020-04-23 21:52:32 +08:00 committed by mergify[bot]
parent cdc3fa5418
commit ad1db975c0
8 changed files with 580 additions and 13 deletions

View File

@ -4,6 +4,7 @@
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
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;

View File

@ -2,6 +2,7 @@
Function prototypes and defines on Memory Only PE COFF loader
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portion Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
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<<RISCV_IMM_BITS)
#define RISCV_CONST_HIGH_PART(VALUE) \
(((VALUE) + (RISCV_IMM_REACH/2)) & ~(RISCV_IMM_REACH-1))
//
// PE/COFF Loader Read Function passed in by caller

View File

@ -3,6 +3,7 @@ IA32 and X64 Specific relocation fixups
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
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

View File

@ -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.<BR>
Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
Portions Copyright (c) 2016 HP Development Company, L.P.<BR>
Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
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;
}

View File

@ -3,6 +3,7 @@ Elf32 Convert solution
Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
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) {

View File

@ -3,6 +3,7 @@ Elf64 convert solution
Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
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,6 +1049,11 @@ WriteSections64 (
SymName = (const UINT8 *)"<unknown>";
}
//
// 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.",
@ -901,6 +1061,7 @@ WriteSections64 (
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);
}

View File

@ -3,6 +3,7 @@ Ported ELF include files from FreeBSD
Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
Portion Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
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_ */

View File

@ -6,6 +6,7 @@
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
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