BaseTools: Update GenFw/GenFv to support LoongArch platform.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4053 C code changes for building EDK2 LoongArch platform. For definitions of PE/COFF and LOONGARCH relocation types, see the "Machine Types" and "Basic Relocation Types" sections of this URL for LOONGARCH values: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format Cc: Bob Feng <bob.c.feng@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Yuwei Chen <yuwei.chen@intel.com> Signed-off-by: Chao Li <lichao@loongson.cn> Co-authored-by: Dongyan Qian <qiandongyan@loongson.cn> Co-authored-by: Baoqi Zhang <zhangbaoqi@loongson.cn> Co-authored-by: Yang Zhou <zhouyang@loongson.cn> Co-authored-by: Xiaotian Wu <wuxiaotian@loongson.cn> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
This commit is contained in:
@@ -4,6 +4,7 @@ Elf64 convert solution
|
||||
Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
|
||||
Portions copyright (c) 2013-2022, ARM Ltd. All rights reserved.<BR>
|
||||
Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
|
||||
Portions Copyright (c) 2022, Loongson Technology Corporation Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
@@ -177,7 +178,7 @@ 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) || (mEhdr->e_machine == EM_RISCV64))) {
|
||||
if (!((mEhdr->e_machine == EM_X86_64) || (mEhdr->e_machine == EM_AARCH64) || (mEhdr->e_machine == EM_RISCV64) || (mEhdr->e_machine == EM_LOONGARCH))) {
|
||||
Warning (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf64 machine.");
|
||||
}
|
||||
if (mEhdr->e_version != EV_CURRENT) {
|
||||
@@ -799,6 +800,7 @@ ScanSections64 (
|
||||
case EM_X86_64:
|
||||
case EM_AARCH64:
|
||||
case EM_RISCV64:
|
||||
case EM_LOONGARCH:
|
||||
mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64);
|
||||
break;
|
||||
default:
|
||||
@@ -1088,6 +1090,10 @@ ScanSections64 (
|
||||
NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_RISCV64;
|
||||
NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
|
||||
break;
|
||||
case EM_LOONGARCH:
|
||||
NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_LOONGARCH64;
|
||||
NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
|
||||
break;
|
||||
|
||||
default:
|
||||
VerboseMsg ("%s unknown e_machine type. Assume X64", (UINTN)mEhdr->e_machine);
|
||||
@@ -1333,10 +1339,10 @@ WriteSections64 (
|
||||
}
|
||||
|
||||
//
|
||||
// Skip error on EM_RISCV64 becasue no symble name is built
|
||||
// from RISC-V toolchain.
|
||||
// Skip error on EM_RISCV64 and EM_LOONGARCH because no symbol name is built
|
||||
// from RISC-V and LoongArch toolchain.
|
||||
//
|
||||
if (mEhdr->e_machine != EM_RISCV64) {
|
||||
if ((mEhdr->e_machine != EM_RISCV64) && (mEhdr->e_machine != EM_LOONGARCH)) {
|
||||
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.",
|
||||
@@ -1618,6 +1624,178 @@ WriteSections64 (
|
||||
// Write section for RISC-V 64 architecture.
|
||||
//
|
||||
WriteSectionRiscV64 (Rel, Targ, SymShdr, Sym);
|
||||
} else if (mEhdr->e_machine == EM_LOONGARCH) {
|
||||
switch (ELF_R_TYPE(Rel->r_info)) {
|
||||
INT64 Offset;
|
||||
INT32 Lo, Hi;
|
||||
|
||||
case R_LARCH_SOP_PUSH_ABSOLUTE:
|
||||
//
|
||||
// Absolute relocation.
|
||||
//
|
||||
*(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx];
|
||||
break;
|
||||
|
||||
case R_LARCH_MARK_LA:
|
||||
case R_LARCH_64:
|
||||
case R_LARCH_NONE:
|
||||
case R_LARCH_32:
|
||||
case R_LARCH_RELATIVE:
|
||||
case R_LARCH_COPY:
|
||||
case R_LARCH_JUMP_SLOT:
|
||||
case R_LARCH_TLS_DTPMOD32:
|
||||
case R_LARCH_TLS_DTPMOD64:
|
||||
case R_LARCH_TLS_DTPREL32:
|
||||
case R_LARCH_TLS_DTPREL64:
|
||||
case R_LARCH_TLS_TPREL32:
|
||||
case R_LARCH_TLS_TPREL64:
|
||||
case R_LARCH_IRELATIVE:
|
||||
case R_LARCH_MARK_PCREL:
|
||||
case R_LARCH_SOP_PUSH_PCREL:
|
||||
case R_LARCH_SOP_PUSH_DUP:
|
||||
case R_LARCH_SOP_PUSH_GPREL:
|
||||
case R_LARCH_SOP_PUSH_TLS_TPREL:
|
||||
case R_LARCH_SOP_PUSH_TLS_GOT:
|
||||
case R_LARCH_SOP_PUSH_TLS_GD:
|
||||
case R_LARCH_SOP_PUSH_PLT_PCREL:
|
||||
case R_LARCH_SOP_ASSERT:
|
||||
case R_LARCH_SOP_NOT:
|
||||
case R_LARCH_SOP_SUB:
|
||||
case R_LARCH_SOP_SL:
|
||||
case R_LARCH_SOP_SR:
|
||||
case R_LARCH_SOP_ADD:
|
||||
case R_LARCH_SOP_AND:
|
||||
case R_LARCH_SOP_IF_ELSE:
|
||||
case R_LARCH_SOP_POP_32_S_10_5:
|
||||
case R_LARCH_SOP_POP_32_U_10_12:
|
||||
case R_LARCH_SOP_POP_32_S_10_12:
|
||||
case R_LARCH_SOP_POP_32_S_10_16:
|
||||
case R_LARCH_SOP_POP_32_S_10_16_S2:
|
||||
case R_LARCH_SOP_POP_32_S_5_20:
|
||||
case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
|
||||
case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
|
||||
case R_LARCH_SOP_POP_32_U:
|
||||
case R_LARCH_ADD8:
|
||||
case R_LARCH_ADD16:
|
||||
case R_LARCH_ADD24:
|
||||
case R_LARCH_ADD32:
|
||||
case R_LARCH_ADD64:
|
||||
case R_LARCH_SUB8:
|
||||
case R_LARCH_SUB16:
|
||||
case R_LARCH_SUB24:
|
||||
case R_LARCH_SUB32:
|
||||
case R_LARCH_SUB64:
|
||||
case R_LARCH_GNU_VTINHERIT:
|
||||
case R_LARCH_GNU_VTENTRY:
|
||||
case R_LARCH_B16:
|
||||
case R_LARCH_B21:
|
||||
case R_LARCH_B26:
|
||||
case R_LARCH_ABS_HI20:
|
||||
case R_LARCH_ABS_LO12:
|
||||
case R_LARCH_ABS64_LO20:
|
||||
case R_LARCH_ABS64_HI12:
|
||||
case R_LARCH_PCALA_LO12:
|
||||
case R_LARCH_PCALA64_LO20:
|
||||
case R_LARCH_PCALA64_HI12:
|
||||
case R_LARCH_GOT_PC_LO12:
|
||||
case R_LARCH_GOT64_PC_LO20:
|
||||
case R_LARCH_GOT64_PC_HI12:
|
||||
case R_LARCH_GOT64_HI20:
|
||||
case R_LARCH_GOT64_LO12:
|
||||
case R_LARCH_GOT64_LO20:
|
||||
case R_LARCH_GOT64_HI12:
|
||||
case R_LARCH_TLS_LE_HI20:
|
||||
case R_LARCH_TLS_LE_LO12:
|
||||
case R_LARCH_TLS_LE64_LO20:
|
||||
case R_LARCH_TLS_LE64_HI12:
|
||||
case R_LARCH_TLS_IE_PC_HI20:
|
||||
case R_LARCH_TLS_IE_PC_LO12:
|
||||
case R_LARCH_TLS_IE64_PC_LO20:
|
||||
case R_LARCH_TLS_IE64_PC_HI12:
|
||||
case R_LARCH_TLS_IE64_HI20:
|
||||
case R_LARCH_TLS_IE64_LO12:
|
||||
case R_LARCH_TLS_IE64_LO20:
|
||||
case R_LARCH_TLS_IE64_HI12:
|
||||
case R_LARCH_TLS_LD_PC_HI20:
|
||||
case R_LARCH_TLS_LD64_HI20:
|
||||
case R_LARCH_TLS_GD_PC_HI20:
|
||||
case R_LARCH_TLS_GD64_HI20:
|
||||
case R_LARCH_RELAX:
|
||||
//
|
||||
// These types are not used or do not require fixup.
|
||||
//
|
||||
break;
|
||||
|
||||
case R_LARCH_GOT_PC_HI20:
|
||||
Offset = Sym->st_value - (UINTN)(Targ - mCoffFile);
|
||||
if (Offset < 0) {
|
||||
Offset = (UINTN)(Targ - mCoffFile) - Sym->st_value;
|
||||
Hi = Offset & ~0xfff;
|
||||
Lo = (INT32)((Offset & 0xfff) << 20) >> 20;
|
||||
if ((Lo < 0) && (Lo > -2048)) {
|
||||
Hi += 0x1000;
|
||||
Lo = ~(0x1000 - Lo) + 1;
|
||||
}
|
||||
Hi = ~Hi + 1;
|
||||
Lo = ~Lo + 1;
|
||||
} else {
|
||||
Hi = Offset & ~0xfff;
|
||||
Lo = (INT32)((Offset & 0xfff) << 20) >> 20;
|
||||
if (Lo < 0) {
|
||||
Hi += 0x1000;
|
||||
Lo = ~(0x1000 - Lo) + 1;
|
||||
}
|
||||
}
|
||||
// Re-encode the offset as PCADDU12I + ADDI.D(Convert LD.D) instruction
|
||||
*(UINT32 *)Targ &= 0x1f;
|
||||
*(UINT32 *)Targ |= 0x1c000000;
|
||||
*(UINT32 *)Targ |= (((Hi >> 12) & 0xfffff) << 5);
|
||||
*(UINT32 *)(Targ + 4) &= 0x3ff;
|
||||
*(UINT32 *)(Targ + 4) |= 0x2c00000 | ((Lo & 0xfff) << 10);
|
||||
break;
|
||||
|
||||
//
|
||||
// Attempt to convert instruction.
|
||||
//
|
||||
case R_LARCH_PCALA_HI20:
|
||||
// Decode the PCALAU12I instruction and the instruction that following it.
|
||||
Offset = ((INT32)((*(UINT32 *)Targ & 0x1ffffe0) << 7));
|
||||
Offset += ((INT32)((*(UINT32 *)(Targ + 4) & 0x3ffc00) << 10) >> 20);
|
||||
//
|
||||
// PCALA offset is relative to the previous page boundary,
|
||||
// whereas PCADD offset is relative to the instruction itself.
|
||||
// So fix up the offset so it points to the page containing
|
||||
// the symbol.
|
||||
//
|
||||
Offset -= (UINTN)(Targ - mCoffFile) & 0xfff;
|
||||
if (Offset < 0) {
|
||||
Offset = -Offset;
|
||||
Hi = Offset & ~0xfff;
|
||||
Lo = (INT32)((Offset & 0xfff) << 20) >> 20;
|
||||
if ((Lo < 0) && (Lo > -2048)) {
|
||||
Hi += 0x1000;
|
||||
Lo = ~(0x1000 - Lo) + 1;
|
||||
}
|
||||
Hi = ~Hi + 1;
|
||||
Lo = ~Lo + 1;
|
||||
} else {
|
||||
Hi = Offset & ~0xfff;
|
||||
Lo = (INT32)((Offset & 0xfff) << 20) >> 20;
|
||||
if (Lo < 0) {
|
||||
Hi += 0x1000;
|
||||
Lo = ~(0x1000 - Lo) + 1;
|
||||
}
|
||||
}
|
||||
// Convert the first instruction from PCALAU12I to PCADDU12I and re-encode the offset into them.
|
||||
*(UINT32 *)Targ &= 0x1f;
|
||||
*(UINT32 *)Targ |= 0x1c000000;
|
||||
*(UINT32 *)Targ |= (((Hi >> 12) & 0xfffff) << 5);
|
||||
*(UINT32 *)(Targ + 4) &= 0xffc003ff;
|
||||
*(UINT32 *)(Targ + 4) |= (Lo & 0xfff) << 10;
|
||||
break;
|
||||
default:
|
||||
Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_LOONGARCH relocation 0x%x.", mInImageName, (unsigned) ELF64_R_TYPE(Rel->r_info));
|
||||
}
|
||||
} else {
|
||||
Error (NULL, 0, 3000, "Invalid", "Not a supported machine type");
|
||||
}
|
||||
@@ -1850,6 +2028,113 @@ WriteRelocations64 (
|
||||
default:
|
||||
Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_RISCV64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));
|
||||
}
|
||||
} else if (mEhdr->e_machine == EM_LOONGARCH) {
|
||||
switch (ELF_R_TYPE(Rel->r_info)) {
|
||||
case R_LARCH_MARK_LA:
|
||||
CoffAddFixup(
|
||||
(UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]
|
||||
+ (Rel->r_offset - SecShdr->sh_addr)),
|
||||
EFI_IMAGE_REL_BASED_LOONGARCH64_MARK_LA);
|
||||
break;
|
||||
case R_LARCH_64:
|
||||
CoffAddFixup(
|
||||
(UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info]
|
||||
+ (Rel->r_offset - SecShdr->sh_addr)),
|
||||
EFI_IMAGE_REL_BASED_DIR64);
|
||||
break;
|
||||
case R_LARCH_NONE:
|
||||
case R_LARCH_32:
|
||||
case R_LARCH_RELATIVE:
|
||||
case R_LARCH_COPY:
|
||||
case R_LARCH_JUMP_SLOT:
|
||||
case R_LARCH_TLS_DTPMOD32:
|
||||
case R_LARCH_TLS_DTPMOD64:
|
||||
case R_LARCH_TLS_DTPREL32:
|
||||
case R_LARCH_TLS_DTPREL64:
|
||||
case R_LARCH_TLS_TPREL32:
|
||||
case R_LARCH_TLS_TPREL64:
|
||||
case R_LARCH_IRELATIVE:
|
||||
case R_LARCH_MARK_PCREL:
|
||||
case R_LARCH_SOP_PUSH_PCREL:
|
||||
case R_LARCH_SOP_PUSH_ABSOLUTE:
|
||||
case R_LARCH_SOP_PUSH_DUP:
|
||||
case R_LARCH_SOP_PUSH_GPREL:
|
||||
case R_LARCH_SOP_PUSH_TLS_TPREL:
|
||||
case R_LARCH_SOP_PUSH_TLS_GOT:
|
||||
case R_LARCH_SOP_PUSH_TLS_GD:
|
||||
case R_LARCH_SOP_PUSH_PLT_PCREL:
|
||||
case R_LARCH_SOP_ASSERT:
|
||||
case R_LARCH_SOP_NOT:
|
||||
case R_LARCH_SOP_SUB:
|
||||
case R_LARCH_SOP_SL:
|
||||
case R_LARCH_SOP_SR:
|
||||
case R_LARCH_SOP_ADD:
|
||||
case R_LARCH_SOP_AND:
|
||||
case R_LARCH_SOP_IF_ELSE:
|
||||
case R_LARCH_SOP_POP_32_S_10_5:
|
||||
case R_LARCH_SOP_POP_32_U_10_12:
|
||||
case R_LARCH_SOP_POP_32_S_10_12:
|
||||
case R_LARCH_SOP_POP_32_S_10_16:
|
||||
case R_LARCH_SOP_POP_32_S_10_16_S2:
|
||||
case R_LARCH_SOP_POP_32_S_5_20:
|
||||
case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
|
||||
case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
|
||||
case R_LARCH_SOP_POP_32_U:
|
||||
case R_LARCH_ADD8:
|
||||
case R_LARCH_ADD16:
|
||||
case R_LARCH_ADD24:
|
||||
case R_LARCH_ADD32:
|
||||
case R_LARCH_ADD64:
|
||||
case R_LARCH_SUB8:
|
||||
case R_LARCH_SUB16:
|
||||
case R_LARCH_SUB24:
|
||||
case R_LARCH_SUB32:
|
||||
case R_LARCH_SUB64:
|
||||
case R_LARCH_GNU_VTINHERIT:
|
||||
case R_LARCH_GNU_VTENTRY:
|
||||
case R_LARCH_B16:
|
||||
case R_LARCH_B21:
|
||||
case R_LARCH_B26:
|
||||
case R_LARCH_ABS_HI20:
|
||||
case R_LARCH_ABS_LO12:
|
||||
case R_LARCH_ABS64_LO20:
|
||||
case R_LARCH_ABS64_HI12:
|
||||
case R_LARCH_PCALA_HI20:
|
||||
case R_LARCH_PCALA_LO12:
|
||||
case R_LARCH_PCALA64_LO20:
|
||||
case R_LARCH_PCALA64_HI12:
|
||||
case R_LARCH_GOT_PC_HI20:
|
||||
case R_LARCH_GOT_PC_LO12:
|
||||
case R_LARCH_GOT64_PC_LO20:
|
||||
case R_LARCH_GOT64_PC_HI12:
|
||||
case R_LARCH_GOT64_HI20:
|
||||
case R_LARCH_GOT64_LO12:
|
||||
case R_LARCH_GOT64_LO20:
|
||||
case R_LARCH_GOT64_HI12:
|
||||
case R_LARCH_TLS_LE_HI20:
|
||||
case R_LARCH_TLS_LE_LO12:
|
||||
case R_LARCH_TLS_LE64_LO20:
|
||||
case R_LARCH_TLS_LE64_HI12:
|
||||
case R_LARCH_TLS_IE_PC_HI20:
|
||||
case R_LARCH_TLS_IE_PC_LO12:
|
||||
case R_LARCH_TLS_IE64_PC_LO20:
|
||||
case R_LARCH_TLS_IE64_PC_HI12:
|
||||
case R_LARCH_TLS_IE64_HI20:
|
||||
case R_LARCH_TLS_IE64_LO12:
|
||||
case R_LARCH_TLS_IE64_LO20:
|
||||
case R_LARCH_TLS_IE64_HI12:
|
||||
case R_LARCH_TLS_LD_PC_HI20:
|
||||
case R_LARCH_TLS_LD64_HI20:
|
||||
case R_LARCH_TLS_GD_PC_HI20:
|
||||
case R_LARCH_TLS_GD64_HI20:
|
||||
case R_LARCH_RELAX:
|
||||
//
|
||||
// These types are not used or do not require fixup in PE format files.
|
||||
//
|
||||
break;
|
||||
default:
|
||||
Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_LOONGARCH relocation 0x%x.", mInImageName, (unsigned) ELF64_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