Browse Source

Initial support for RISCV64

Add the RISCV64 architecture

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Heinrich Schuchardt 4 years ago
parent
commit
b95f138fa1

+ 2 - 0
Make.defaults

@@ -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 - 0
gnuefi/crt0-efi-riscv64.S

@@ -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 - 0
gnuefi/elf_riscv64_efi.lds

@@ -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 - 0
gnuefi/reloc_riscv64.c

@@ -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;
+}

+ 2 - 0
inc/efi.h

@@ -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

+ 2 - 0
inc/efilib.h

@@ -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"

+ 2 - 0
inc/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 - 0
inc/riscv64/efibind.h

@@ -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 - 0
inc/riscv64/efilibplat.h

@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+VOID
+InitializeLibPlatform (
+    IN EFI_HANDLE           ImageHandle,
+    IN EFI_SYSTEM_TABLE     *SystemTable
+    );

+ 1 - 1
lib/Makefile

@@ -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 - 0
lib/riscv64/initplat.c

@@ -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 - 0
lib/riscv64/math.c

@@ -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 - 0
lib/riscv64/setjmp.S

@@ -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