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:
committed by
mergify[bot]
parent
cdc3fa5418
commit
ad1db975c0
@ -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,12 +1049,18 @@ WriteSections64 (
|
||||
SymName = (const UINT8 *)"<unknown>";
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user