[riscv] Add support for the RISC-V CPU architecture

Add support for building iPXE as a 64-bit or 32-bit RISC-V binary, for
either UEFI or Linux userspace platforms.  For example:

  # RISC-V 64-bit UEFI
  make CROSS=riscv64-linux-gnu- bin-riscv64-efi/ipxe.efi

  # RISC-V 32-bit UEFI
  make CROSS=riscv64-linux-gnu- bin-riscv32-efi/ipxe.efi

  # RISC-V 64-bit Linux
  make CROSS=riscv64-linux-gnu- bin-riscv64-linux/tests.linux
  qemu-riscv64 -L /usr/riscv64-linux-gnu/sys-root \
               ./bin-riscv64-linux/tests.linux

  # RISC-V 32-bit Linux
  make CROSS=riscv64-linux-gnu- SYSROOT=/usr/riscv32-linux-gnu/sys-root \
       bin-riscv32-linux/tests.linux
  qemu-riscv32 -L /usr/riscv32-linux-gnu/sys-root \
               ./bin-riscv32-linux/tests.linux

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2024-09-15 10:54:04 +01:00
parent 68db9a3cb3
commit c215048dda
42 changed files with 2405 additions and 0 deletions

View File

@@ -91,11 +91,13 @@ static void read_pe_info ( void *pe, uint16_t *machine,
switch ( *machine ) {
case EFI_IMAGE_MACHINE_IA32:
case EFI_IMAGE_MACHINE_ARMTHUMB_MIXED:
case EFI_IMAGE_MACHINE_RISCV32:
*subsystem = nt->nt32.OptionalHeader.Subsystem;
break;
case EFI_IMAGE_MACHINE_X64:
case EFI_IMAGE_MACHINE_AARCH64:
case EFI_IMAGE_MACHINE_LOONGARCH64:
case EFI_IMAGE_MACHINE_RISCV64:
*subsystem = nt->nt64.OptionalHeader.Subsystem;
break;
default:

View File

@@ -83,6 +83,9 @@
#ifndef EM_AARCH64
#define EM_AARCH64 183
#endif
#ifndef EM_RISCV
#define EM_RISCV 243
#endif
#ifndef EM_LOONGARCH
#define EM_LOONGARCH 258
#endif
@@ -167,6 +170,45 @@
#ifndef R_LARCH_PCREL20_S2
#define R_LARCH_PCREL20_S2 103
#endif
#ifndef R_RISCV_NONE
#define R_RISCV_NONE 0
#endif
#ifndef R_RISCV_32
#define R_RISCV_32 1
#endif
#ifndef R_RISCV_64
#define R_RISCV_64 2
#endif
#ifndef R_RISCV_BRANCH
#define R_RISCV_BRANCH 16
#endif
#ifndef R_RISCV_JAL
#define R_RISCV_JAL 17
#endif
#ifndef R_RISCV_PCREL_HI20
#define R_RISCV_PCREL_HI20 23
#endif
#ifndef R_RISCV_PCREL_LO12_I
#define R_RISCV_PCREL_LO12_I 24
#endif
#ifndef R_RISCV_PCREL_LO12_S
#define R_RISCV_PCREL_LO12_S 25
#endif
#ifndef R_RISCV_ADD32
#define R_RISCV_ADD32 35
#endif
#ifndef R_RISCV_SUB32
#define R_RISCV_SUB32 39
#endif
#ifndef R_RISCV_RVC_BRANCH
#define R_RISCV_RVC_BRANCH 44
#endif
#ifndef R_RISCV_RVC_JUMP
#define R_RISCV_RVC_JUMP 45
#endif
#ifndef R_RISCV_RELAX
#define R_RISCV_RELAX 51
#endif
#ifndef R_X86_64_GOTPCRELX
#define R_X86_64_GOTPCRELX 41
#endif
@@ -596,6 +638,11 @@ static void set_machine ( struct elf_file *elf, struct pe_header *pe_header ) {
case EM_LOONGARCH:
machine = EFI_IMAGE_MACHINE_LOONGARCH64;
break;
case EM_RISCV:
machine = ( ( ELFCLASS == ELFCLASS64 ) ?
EFI_IMAGE_MACHINE_RISCV64 :
EFI_IMAGE_MACHINE_RISCV32 );
break;
default:
eprintf ( "Unknown ELF architecture %d\n", ehdr->e_machine );
exit ( 1 );
@@ -828,16 +875,19 @@ static void process_reloc ( struct elf_file *elf, const Elf_Shdr *shdr,
case ELF_MREL ( EM_AARCH64, R_AARCH64_NONE ) :
case ELF_MREL ( EM_AARCH64, R_AARCH64_NULL ) :
case ELF_MREL ( EM_LOONGARCH, R_LARCH_NONE ) :
case ELF_MREL ( EM_RISCV, R_RISCV_NONE ) :
/* Ignore dummy relocations used by REQUIRE_SYMBOL() */
break;
case ELF_MREL ( EM_386, R_386_32 ) :
case ELF_MREL ( EM_ARM, R_ARM_ABS32 ) :
case ELF_MREL ( EM_RISCV, R_RISCV_32 ) :
/* Generate a 4-byte PE relocation */
generate_pe_reloc ( pe_reltab, offset, 4 );
break;
case ELF_MREL ( EM_X86_64, R_X86_64_64 ) :
case ELF_MREL ( EM_AARCH64, R_AARCH64_ABS64 ) :
case ELF_MREL ( EM_LOONGARCH, R_LARCH_64 ) :
case ELF_MREL ( EM_RISCV, R_RISCV_64 ) :
/* Generate an 8-byte PE relocation */
generate_pe_reloc ( pe_reltab, offset, 8 );
break;
@@ -869,16 +919,31 @@ static void process_reloc ( struct elf_file *elf, const Elf_Shdr *shdr,
case ELF_MREL ( EM_LOONGARCH, R_LARCH_GOT_PC_HI20 ):
case ELF_MREL ( EM_LOONGARCH, R_LARCH_GOT_PC_LO12 ):
case ELF_MREL ( EM_LOONGARCH, R_LARCH_PCREL20_S2 ):
case ELF_MREL ( EM_RISCV, R_RISCV_BRANCH ) :
case ELF_MREL ( EM_RISCV, R_RISCV_JAL ) :
case ELF_MREL ( EM_RISCV, R_RISCV_PCREL_HI20 ) :
case ELF_MREL ( EM_RISCV, R_RISCV_PCREL_LO12_I ) :
case ELF_MREL ( EM_RISCV, R_RISCV_PCREL_LO12_S ) :
case ELF_MREL ( EM_RISCV, R_RISCV_RVC_BRANCH ) :
case ELF_MREL ( EM_RISCV, R_RISCV_RVC_JUMP ) :
/* Skip PC-relative relocations; all relative
* offsets remain unaltered when the object is
* loaded.
*/
break;
case ELF_MREL ( EM_LOONGARCH, R_LARCH_RELAX ):
case ELF_MREL ( EM_RISCV, R_RISCV_RELAX ) :
/* Relocation can be relaxed (optimized out).
* Ignore it for now.
*/
break;
case ELF_MREL ( EM_RISCV, R_RISCV_ADD32 ) :
case ELF_MREL ( EM_RISCV, R_RISCV_SUB32 ) :
/* Ignore label difference relocations since
* we do not perform any relocations that can
* result in altered label differences.
*/
break;
case ELF_MREL ( EM_X86_64, R_X86_64_32 ) :
/* Ignore 32-bit relocations in a hybrid
* 32-bit BIOS and 64-bit UEFI binary,

View File

@@ -78,6 +78,12 @@ efi_boot_name() {
"64aa" )
echo "BOOTAA64.EFI"
;;
"6450" )
echo "BOOTRISCV64.EFI"
;;
"3250" )
echo "BOOTRISCV32.EFI"
;;
* )
echo "${FILENAME}: unrecognised EFI architecture ${ARCH}" >&2
exit 1