Initial support for RISCV64
Add the RISCV64 architecture Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
parent
dfdcd7eff3
commit
b95f138fa1
@ -142,10 +142,12 @@ endif
|
||||
ifneq ($(ARCH),aarch64)
|
||||
ifneq ($(ARCH),arm)
|
||||
ifneq ($(ARCH),mips64el)
|
||||
ifneq ($(ARCH),riscv64)
|
||||
export HAVE_EFI_OBJCOPY=y
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(ARCH),arm)
|
||||
export LIBGCC=$(shell $(CC) $(ARCH3264) -print-libgcc-file-name)
|
||||
|
136
gnuefi/crt0-efi-riscv64.S
Normal file
136
gnuefi/crt0-efi-riscv64.S
Normal file
@ -0,0 +1,136 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
|
||||
* Copright (C) 2018 Alexander Graf <agraf@suse.de>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice and this list of conditions, without modification.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation;
|
||||
* either version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef EFI_SUBSYSTEM
|
||||
#define EFI_SUBSYSTEM 10
|
||||
#endif
|
||||
|
||||
.section .text.head
|
||||
|
||||
/*
|
||||
* Magic "MZ" signature for PE/COFF
|
||||
*/
|
||||
.globl ImageBase
|
||||
ImageBase:
|
||||
.ascii "MZ"
|
||||
.skip 58 // 'MZ' + pad + offset == 64
|
||||
.long pe_header - ImageBase // Offset to the PE header.
|
||||
pe_header:
|
||||
.ascii "PE"
|
||||
.short 0
|
||||
coff_header:
|
||||
.short 0x5064 // riscv64
|
||||
.short 2 // nr_sections
|
||||
.long 0 // TimeDateStamp
|
||||
.long 0 // PointerToSymbolTable
|
||||
.long 1 // NumberOfSymbols
|
||||
.short section_table - optional_header // SizeOfOptionalHeader
|
||||
.short 0x206 // Characteristics.
|
||||
// IMAGE_FILE_DEBUG_STRIPPED |
|
||||
// IMAGE_FILE_EXECUTABLE_IMAGE |
|
||||
// IMAGE_FILE_LINE_NUMS_STRIPPED
|
||||
optional_header:
|
||||
.short 0x20b // PE32+ format
|
||||
.byte 0x02 // MajorLinkerVersion
|
||||
.byte 0x14 // MinorLinkerVersion
|
||||
.long _data - _start // SizeOfCode
|
||||
.long _data_size // SizeOfInitializedData
|
||||
.long 0 // SizeOfUninitializedData
|
||||
.long _start - ImageBase // AddressOfEntryPoint
|
||||
.long _start - ImageBase // BaseOfCode
|
||||
|
||||
extra_header_fields:
|
||||
.quad 0 // ImageBase
|
||||
.long 0x1000 // SectionAlignment
|
||||
.long 0x200 // FileAlignment
|
||||
.short 0 // MajorOperatingSystemVersion
|
||||
.short 0 // MinorOperatingSystemVersion
|
||||
.short 0 // MajorImageVersion
|
||||
.short 0 // MinorImageVersion
|
||||
.short 0 // MajorSubsystemVersion
|
||||
.short 0 // MinorSubsystemVersion
|
||||
.long 0 // Win32VersionValue
|
||||
|
||||
.long _edata - ImageBase // SizeOfImage
|
||||
|
||||
// Everything before the kernel image is considered part of the header
|
||||
.long _start - ImageBase // SizeOfHeaders
|
||||
.long 0 // CheckSum
|
||||
.short EFI_SUBSYSTEM // Subsystem
|
||||
.short 0 // DllCharacteristics
|
||||
.quad 0 // SizeOfStackReserve
|
||||
.quad 0 // SizeOfStackCommit
|
||||
.quad 0 // SizeOfHeapReserve
|
||||
.quad 0 // SizeOfHeapCommit
|
||||
.long 0 // LoaderFlags
|
||||
.long 0x6 // NumberOfRvaAndSizes
|
||||
|
||||
.quad 0 // ExportTable
|
||||
.quad 0 // ImportTable
|
||||
.quad 0 // ResourceTable
|
||||
.quad 0 // ExceptionTable
|
||||
.quad 0 // CertificationTable
|
||||
.quad 0 // BaseRelocationTable
|
||||
|
||||
// Section table
|
||||
section_table:
|
||||
/*
|
||||
* The EFI application loader requires a relocation section
|
||||
* because EFI applications must be relocatable. This is a
|
||||
* dummy section as far as we are concerned.
|
||||
*/
|
||||
.ascii ".reloc\0\0"
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0 // SizeOfRawData
|
||||
.long 0 // PointerToRawData
|
||||
.long 0 // PointerToRelocations
|
||||
.long 0 // PointerToLineNumbers
|
||||
.short 0 // NumberOfRelocations
|
||||
.short 0 // NumberOfLineNumbers
|
||||
.long 0x42100040 // Characteristics (section flags)
|
||||
|
||||
.ascii ".text\0\0\0"
|
||||
.long _edata - _start // VirtualSize
|
||||
.long _start - ImageBase // VirtualAddress
|
||||
.long _edata - _start // SizeOfRawData
|
||||
.long _start - ImageBase // PointerToRawData
|
||||
|
||||
.long 0 // PointerToRelocations (0 for executables)
|
||||
.long 0 // PointerToLineNumbers (0 for executables)
|
||||
.short 0 // NumberOfRelocations (0 for executables)
|
||||
.short 0 // NumberOfLineNumbers (0 for executables)
|
||||
.long 0xe0500020 // Characteristics (section flags)
|
||||
|
||||
.align 12
|
||||
.globl _start
|
||||
_start:
|
||||
addi sp, sp, -24
|
||||
sd a0, 0(sp)
|
||||
sd a1, 8(sp)
|
||||
sd ra, 16(sp)
|
||||
lla a0, ImageBase
|
||||
lla a1, _DYNAMIC
|
||||
call _relocate
|
||||
bne a0, zero, 0f
|
||||
ld a1, 8(sp)
|
||||
ld a0, 0(sp)
|
||||
call efi_main
|
||||
ld ra, 16(sp)
|
||||
0: addi sp, sp, 24
|
||||
ret
|
77
gnuefi/elf_riscv64_efi.lds
Normal file
77
gnuefi/elf_riscv64_efi.lds
Normal file
@ -0,0 +1,77 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv")
|
||||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(_start)
|
||||
SECTIONS {
|
||||
.text 0x0 :
|
||||
{
|
||||
_text = .;
|
||||
*(.text.head)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
*(.srodata)
|
||||
*(.rodata*)
|
||||
. = ALIGN(16);
|
||||
}
|
||||
_etext = .;
|
||||
_text_size = . - _text;
|
||||
.dynamic :
|
||||
{ *(.dynamic) }
|
||||
.data :
|
||||
ALIGN(4096)
|
||||
{
|
||||
_data = .;
|
||||
*(.sdata)
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.data.*)
|
||||
*(.got.plt)
|
||||
*(.got)
|
||||
|
||||
/* the EFI loader doesn't seem to like a .bss section, so we stick
|
||||
it all into .data: */
|
||||
. = ALIGN(16);
|
||||
_bss = .;
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
. = ALIGN(16);
|
||||
_bss_end = .;
|
||||
}
|
||||
|
||||
.rela.text :
|
||||
{ *(.rela.text) *(.rela.text*) }
|
||||
.rela.dyn :
|
||||
{ *(.rela.dyn) }
|
||||
.rela.plt :
|
||||
{ *(.rela.plt) }
|
||||
.rela.got :
|
||||
{ *(.rela.got) }
|
||||
.rela.data :
|
||||
{ *(.rela.data) *(.rela.data*) }
|
||||
. = ALIGN(512);
|
||||
_edata = .;
|
||||
_data_size = . - _data;
|
||||
|
||||
. = ALIGN(4096);
|
||||
.dynsym :
|
||||
{ *(.dynsym) }
|
||||
. = ALIGN(4096);
|
||||
.dynstr :
|
||||
{ *(.dynstr) }
|
||||
. = ALIGN(4096);
|
||||
.note.gnu.build-id :
|
||||
{ *(.note.gnu.build-id) }
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.rel.reloc)
|
||||
*(.eh_frame)
|
||||
*(.note.GNU-stack)
|
||||
}
|
||||
.comment 0 :
|
||||
{ *(.comment) }
|
||||
}
|
91
gnuefi/reloc_riscv64.c
Normal file
91
gnuefi/reloc_riscv64.c
Normal file
@ -0,0 +1,91 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/* reloc_riscv.c - position independent ELF shared object relocator
|
||||
Copyright (C) 2018 Alexander Graf <agraf@suse.de>
|
||||
Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
|
||||
Copyright (C) 1999 Hewlett-Packard Co.
|
||||
Contributed by David Mosberger <davidm@hpl.hp.com>.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
* Neither the name of Hewlett-Packard Co. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <efi.h>
|
||||
|
||||
#include <elf.h>
|
||||
|
||||
#define Elf_Dyn Elf64_Dyn
|
||||
#define Elf_Rela Elf64_Rela
|
||||
#define ELF_R_TYPE ELF64_R_TYPE
|
||||
|
||||
EFI_STATUS EFIAPI _relocate(long ldbase, Elf_Dyn *dyn)
|
||||
{
|
||||
long relsz = 0, relent = 0;
|
||||
Elf_Rela *rel = NULL;
|
||||
unsigned long *addr;
|
||||
int i;
|
||||
|
||||
for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
|
||||
switch (dyn[i].d_tag) {
|
||||
case DT_RELA:
|
||||
rel = (Elf_Rela *)((unsigned long)dyn[i].d_un.d_ptr + ldbase);
|
||||
break;
|
||||
case DT_RELASZ:
|
||||
relsz = dyn[i].d_un.d_val;
|
||||
break;
|
||||
case DT_RELAENT:
|
||||
relent = dyn[i].d_un.d_val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rel && relent == 0)
|
||||
return EFI_SUCCESS;
|
||||
|
||||
if (!rel || relent == 0)
|
||||
return EFI_LOAD_ERROR;
|
||||
|
||||
while (relsz > 0) {
|
||||
/* apply the relocs */
|
||||
switch (ELF_R_TYPE(rel->r_info)) {
|
||||
case R_RISCV_RELATIVE:
|
||||
addr = (unsigned long *)(ldbase + rel->r_offset);
|
||||
*addr = ldbase + rel->r_addend;
|
||||
break;
|
||||
default:
|
||||
/* Panic */
|
||||
while (1) ;
|
||||
}
|
||||
rel = (Elf_Rela *)((char *)rel + relent);
|
||||
relsz -= relent;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
@ -50,6 +50,8 @@ Revision History
|
||||
#include "arm/efibind.h"
|
||||
#elif defined (_M_MIPS64) || defined(__mips64__)
|
||||
#include "mips64el/efibind.h"
|
||||
#elif defined (__riscv) && __riscv_xlen == 64
|
||||
#include "riscv64/efibind.h"
|
||||
#else
|
||||
#error Usupported architecture
|
||||
#endif
|
||||
|
@ -33,6 +33,8 @@ Revision History
|
||||
#include "arm/efilibplat.h"
|
||||
#elif defined (_M_MIPS64) || defined(__mips64__)
|
||||
#include "mips64el/efilibplat.h"
|
||||
#elif defined (__riscv) && __riscv_xlen == 64
|
||||
#include "riscv64/efilibplat.h"
|
||||
#endif
|
||||
#include "efilink.h"
|
||||
#include "efirtlib.h"
|
||||
|
@ -32,6 +32,8 @@ Revision History
|
||||
#include "arm/efilibplat.h"
|
||||
#elif defined (_M_MIPS64) || defined(__mips64__)
|
||||
#include "mips64el/efilibplat.h"
|
||||
#elif defined (__riscv) && __riscv_xlen == 64
|
||||
#include "riscv64/efilibplat.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
31
inc/riscv64/efibind.h
Normal file
31
inc/riscv64/efibind.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define EFIAPI
|
||||
#define EFI_ERROR_MASK 0x8000000000000000
|
||||
#define EFIERR(a) (EFI_ERROR_MASK | a)
|
||||
#define INTERFACE_DECL(x) struct x
|
||||
#define MIN_ALIGNMENT_SIZE 8
|
||||
#define RUNTIMEFUNCTION
|
||||
#define VOID void
|
||||
|
||||
typedef uint8_t BOOLEAN;
|
||||
typedef int64_t INTN;
|
||||
typedef uint64_t UINTN;
|
||||
typedef int8_t INT8;
|
||||
typedef uint8_t UINT8;
|
||||
typedef int16_t INT16;
|
||||
typedef uint16_t UINT16;
|
||||
typedef int32_t INT32;
|
||||
typedef uint32_t UINT32;
|
||||
typedef int64_t INT64;
|
||||
typedef uint64_t UINT64;
|
||||
typedef uint16_t WCHAR;
|
||||
|
||||
#define BREAKPOINT() while(1);
|
||||
#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__)
|
||||
|
||||
#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8))
|
||||
#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16))
|
||||
#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32))
|
7
inc/riscv64/efilibplat.h
Normal file
7
inc/riscv64/efilibplat.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
VOID
|
||||
InitializeLibPlatform (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
@ -64,7 +64,7 @@ endif
|
||||
|
||||
OBJS = $(FILES:%=%.o)
|
||||
|
||||
SUBDIRS = ia32 x86_64 ia64 aarch64 arm mips64el runtime
|
||||
SUBDIRS = ia32 x86_64 ia64 aarch64 arm mips64el riscv64 runtime
|
||||
|
||||
LIBDIRINSTALL = $(INSTALLROOT)$(LIBDIR)
|
||||
|
||||
|
11
lib/riscv64/initplat.c
Normal file
11
lib/riscv64/initplat.c
Normal file
@ -0,0 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
VOID
|
||||
InitializeLibPlatform (
|
||||
IN EFI_HANDLE ImageHandle EFI_UNUSED,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED
|
||||
)
|
||||
{
|
||||
}
|
62
lib/riscv64/math.c
Normal file
62
lib/riscv64/math.c
Normal file
@ -0,0 +1,62 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
/*
|
||||
* This code is based on EDK II MdePkg/Library/BaseLib/Math64.c
|
||||
* Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
/**
|
||||
* LShiftU64() - left shift
|
||||
*/
|
||||
UINT64
|
||||
LShiftU64 (
|
||||
IN UINT64 Operand,
|
||||
IN UINTN Count
|
||||
)
|
||||
{
|
||||
return Operand << Count;
|
||||
}
|
||||
|
||||
/**
|
||||
* RShiftU64() - right shift
|
||||
*/
|
||||
UINT64
|
||||
RShiftU64 (
|
||||
IN UINT64 Operand,
|
||||
IN UINTN Count
|
||||
)
|
||||
{
|
||||
return Operand >> Count;
|
||||
}
|
||||
|
||||
/**
|
||||
* MultU64x32() - multiply
|
||||
*/
|
||||
UINT64
|
||||
MultU64x32 (
|
||||
IN UINT64 Multiplicand,
|
||||
IN UINTN Multiplier
|
||||
)
|
||||
{
|
||||
return Multiplicand * Multiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* DivU64x32() - divide
|
||||
*/
|
||||
UINT64
|
||||
DivU64x32 (
|
||||
IN UINT64 Dividend,
|
||||
IN UINTN Divisor,
|
||||
OUT UINTN *Remainder OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT(Divisor != 0);
|
||||
|
||||
if (Remainder) {
|
||||
*Remainder = Dividend % Divisor;
|
||||
}
|
||||
|
||||
return Dividend / Divisor;
|
||||
}
|
69
lib/riscv64/setjmp.S
Normal file
69
lib/riscv64/setjmp.S
Normal file
@ -0,0 +1,69 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright Heinrich Schuchardt <xypron.glpk@gmx.de>
|
||||
*/
|
||||
|
||||
.text
|
||||
.p2align 3
|
||||
|
||||
#define GREG_LIST \
|
||||
REG_ONE(s0, 0); \
|
||||
REG_ONE(s1, 8); \
|
||||
REG_ONE(s2, 16); \
|
||||
REG_ONE(s3, 24); \
|
||||
REG_ONE(s4, 32); \
|
||||
REG_ONE(s5, 40); \
|
||||
REG_ONE(s6, 48); \
|
||||
REG_ONE(s7, 56); \
|
||||
REG_ONE(s8, 64); \
|
||||
REG_ONE(s9, 72); \
|
||||
REG_ONE(s10, 80); \
|
||||
REG_ONE(s11, 88); \
|
||||
REG_ONE(sp, 96); \
|
||||
REG_ONE(ra, 104);
|
||||
|
||||
#define FREG_LIST \
|
||||
FREG_ONE(fs0, 112); \
|
||||
FREG_ONE(fs1, 120); \
|
||||
FREG_ONE(fs2, 128); \
|
||||
FREG_ONE(fs3, 136); \
|
||||
FREG_ONE(fs4, 144); \
|
||||
FREG_ONE(fs5, 152); \
|
||||
FREG_ONE(fs6, 160); \
|
||||
FREG_ONE(fs7, 168); \
|
||||
FREG_ONE(fs8, 176); \
|
||||
FREG_ONE(fs9, 184); \
|
||||
FREG_ONE(fs10, 192); \
|
||||
FREG_ONE(fs11, 200);
|
||||
|
||||
#define REG_ONE(R, P) sd R, P(a0)
|
||||
#define FREG_ONE(R, P) fsd R, P(a0)
|
||||
|
||||
.globl setjmp
|
||||
.type setjmp, @function
|
||||
|
||||
setjmp:
|
||||
GREG_LIST
|
||||
#ifndef __riscv_float_abi_soft
|
||||
FREG_LIST
|
||||
#endif
|
||||
li a0, 0
|
||||
ret
|
||||
|
||||
#undef REG_ONE
|
||||
#undef FREG_ONE
|
||||
|
||||
#define REG_ONE(R, P) ld R, P(a0)
|
||||
#define FREG_ONE(R, P) fld R, P(a0)
|
||||
|
||||
.globl longjmp
|
||||
.type longjmp, @function
|
||||
|
||||
longjmp:
|
||||
GREG_LIST
|
||||
#ifndef __riscv_float_abi_soft
|
||||
FREG_LIST
|
||||
#endif
|
||||
seqz a0, a1
|
||||
add a0, a0, a1
|
||||
ret
|
Loading…
Reference in New Issue
Block a user