summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2018-05-30 08:43:04 -0400
committerTom Rini <trini@konsulko.com>2018-05-30 08:43:04 -0400
commit964d4f7211ec85b890e852d0226adba0b4f8c1c9 (patch)
tree7b682f156a9bde3b9c3d82a184091bd4445f15cd /arch
parent9c2369a554437f072733c53ba0f5f5384f35b6d3 (diff)
parent6ffea11b89099d72029bc644f7664736ee7ca667 (diff)
Merge git://git.denx.de/u-boot-riscv
Diffstat (limited to 'arch')
-rw-r--r--arch/riscv/Kconfig6
-rw-r--r--arch/riscv/config.mk7
-rw-r--r--arch/riscv/cpu/ax25/Makefile (renamed from arch/riscv/cpu/nx25/Makefile)0
-rw-r--r--arch/riscv/cpu/ax25/cpu.c (renamed from arch/riscv/cpu/nx25/cpu.c)2
-rw-r--r--arch/riscv/cpu/ax25/start.S (renamed from arch/riscv/cpu/nx25/start.S)0
-rw-r--r--arch/riscv/cpu/ax25/u-boot.lds (renamed from arch/riscv/cpu/nx25/u-boot.lds)18
-rw-r--r--arch/riscv/dts/Makefile2
-rw-r--r--arch/riscv/dts/ae250.dts97
-rw-r--r--arch/riscv/dts/ae350.dts149
-rw-r--r--arch/riscv/include/asm/mach-types.h10
-rw-r--r--arch/riscv/include/asm/setjmp.h25
-rw-r--r--arch/riscv/include/asm/u-boot-riscv.h1
-rw-r--r--arch/riscv/lib/Makefile12
-rw-r--r--arch/riscv/lib/bootm.c4
-rw-r--r--arch/riscv/lib/crt0_riscv_efi.S151
-rw-r--r--arch/riscv/lib/elf_riscv32_efi.lds71
-rw-r--r--arch/riscv/lib/elf_riscv64_efi.lds71
-rw-r--r--arch/riscv/lib/reloc_riscv_efi.c98
-rw-r--r--arch/riscv/lib/setjmp.S65
19 files changed, 680 insertions, 109 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index c50be37c97..20a43d88e3 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -8,12 +8,12 @@ choice
prompt "Target select"
optional
-config TARGET_NX25_AE250
- bool "Support nx25-ae250"
+config TARGET_AX25_AE350
+ bool "Support ax25-ae350"
endchoice
-source "board/AndesTech/nx25-ae250/Kconfig"
+source "board/AndesTech/ax25-ae350/Kconfig"
choice
prompt "CPU selection"
diff --git a/arch/riscv/config.mk b/arch/riscv/config.mk
index a7448e2095..219e66683d 100644
--- a/arch/riscv/config.mk
+++ b/arch/riscv/config.mk
@@ -19,15 +19,20 @@ endif
ifdef CONFIG_32BIT
PLATFORM_LDFLAGS += -m $(32bit-emul)
+EFI_LDS := elf_riscv32_efi.lds
endif
ifdef CONFIG_64BIT
PLATFORM_LDFLAGS += -m $(64bit-emul)
+EFI_LDS := elf_riscv64_efi.lds
endif
CONFIG_STANDALONE_LOAD_ADDR = 0x00000000 \
-T $(srctree)/examples/standalone/riscv.lds
PLATFORM_CPPFLAGS += -ffixed-gp -fpic
-PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -gdwarf-2
+PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -gdwarf-2 -ffunction-sections
LDFLAGS_u-boot += --gc-sections -static -pie
+
+EFI_CRT0 := crt0_riscv_efi.o
+EFI_RELOC := reloc_riscv_efi.o
diff --git a/arch/riscv/cpu/nx25/Makefile b/arch/riscv/cpu/ax25/Makefile
index c3f164c122..c3f164c122 100644
--- a/arch/riscv/cpu/nx25/Makefile
+++ b/arch/riscv/cpu/ax25/Makefile
diff --git a/arch/riscv/cpu/nx25/cpu.c b/arch/riscv/cpu/ax25/cpu.c
index 091e9ef59e..ab05b57d4f 100644
--- a/arch/riscv/cpu/nx25/cpu.c
+++ b/arch/riscv/cpu/ax25/cpu.c
@@ -28,5 +28,5 @@ int cleanup_before_linux(void)
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
disable_interrupts();
- panic("nx25-ae250 wdt not support yet.\n");
+ panic("ax25-ae350 wdt not support yet.\n");
}
diff --git a/arch/riscv/cpu/nx25/start.S b/arch/riscv/cpu/ax25/start.S
index 7cd7755190..7cd7755190 100644
--- a/arch/riscv/cpu/nx25/start.S
+++ b/arch/riscv/cpu/ax25/start.S
diff --git a/arch/riscv/cpu/nx25/u-boot.lds b/arch/riscv/cpu/ax25/u-boot.lds
index 86ebc9f4bb..1589babf6c 100644
--- a/arch/riscv/cpu/nx25/u-boot.lds
+++ b/arch/riscv/cpu/ax25/u-boot.lds
@@ -11,7 +11,7 @@ SECTIONS
. = ALIGN(4);
.text :
{
- arch/riscv/cpu/nx25/start.o (.text)
+ arch/riscv/cpu/ax25/start.o (.text)
*(.text)
}
@@ -39,6 +39,22 @@ SECTIONS
. = ALIGN(4);
+ .efi_runtime : {
+ __efi_runtime_start = .;
+ *(efi_runtime_text)
+ *(efi_runtime_data)
+ __efi_runtime_stop = .;
+ }
+
+ .efi_runtime_rel : {
+ __efi_runtime_rel_start = .;
+ *(.relaefi_runtime_text)
+ *(.relaefi_runtime_data)
+ __efi_runtime_rel_stop = .;
+ }
+
+ . = ALIGN(4);
+
/DISCARD/ : { *(.rela.plt*) }
.rela.dyn : {
__rel_dyn_start = .;
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index 793677524a..a1b06ffc6f 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0+
-dtb-$(CONFIG_TARGET_NX25_AE250) += ae250.dtb
+dtb-$(CONFIG_TARGET_AX25_AE350) += ae350.dtb
targets += $(dtb-y)
DTC_FLAGS += -R 4 -p 0x1000
diff --git a/arch/riscv/dts/ae250.dts b/arch/riscv/dts/ae250.dts
deleted file mode 100644
index 9a38345e36..0000000000
--- a/arch/riscv/dts/ae250.dts
+++ /dev/null
@@ -1,97 +0,0 @@
-/dts-v1/;
-/ {
- compatible = "riscv32 nx25";
- #address-cells = <1>;
- #size-cells = <1>;
- interrupt-parent = <&intc>;
-
- aliases {
- uart0 = &serial0;
- ethernet0 = &mac0;
- spi0 = &spi;
- } ;
-
- chosen {
- bootargs = "console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0xf0300000 debug loglevel=7";
- stdout-path = "uart0:38400n8";
- tick-timer = &timer0;
- };
-
- memory@0 {
- device_type = "memory";
- reg = <0x00000000 0x40000000>;
- };
-
- spiclk: virt_100mhz {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <100000000>;
- };
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
- cpu@0 {
- compatible = "andestech,n13";
- reg = <0>;
- /* FIXME: to fill correct frqeuency */
- clock-frequency = <60000000>;
- };
- };
-
- intc: interrupt-controller {
- compatible = "andestech,atnointc010";
- #interrupt-cells = <1>;
- interrupt-controller;
- };
-
- serial0: serial@f0300000 {
- compatible = "andestech,uart16550", "ns16550a";
- reg = <0xf0300000 0x1000>;
- interrupts = <7 4>;
- clock-frequency = <19660800>;
- reg-shift = <2>;
- reg-offset = <32>;
- no-loopback-test = <1>;
- };
-
- timer0: timer@f0400000 {
- compatible = "andestech,atcpit100";
- reg = <0xf0400000 0x1000>;
- interrupts = <2 4>;
- clock-frequency = <40000000>;
- };
-
- mac0: mac@e0100000 {
- compatible = "andestech,atmac100";
- reg = <0xe0100000 0x1000>;
- interrupts = <25 4>;
- };
-
- mmc0: mmc@f0e00000 {
- compatible = "andestech,atsdc010";
- max-frequency = <100000000>;
- fifo-depth = <0x10>;
- reg = <0xf0e00000 0x1000>;
- interrupts = <17 4>;
- cap-sd-highspeed;
- };
-
- spi: spi@f0b00000 {
- compatible = "andestech,atcspi200";
- reg = <0xf0b00000 0x1000>;
- #address-cells = <1>;
- #size-cells = <0>;
- num-cs = <1>;
- clocks = <&spiclk>;
- interrupts = <3 4>;
- flash@0 {
- compatible = "spi-flash";
- spi-max-frequency = <50000000>;
- reg = <0>;
- spi-cpol;
- spi-cpha;
- };
- };
-
-};
diff --git a/arch/riscv/dts/ae350.dts b/arch/riscv/dts/ae350.dts
new file mode 100644
index 0000000000..2927e4151b
--- /dev/null
+++ b/arch/riscv/dts/ae350.dts
@@ -0,0 +1,149 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "andestech,ax25";
+ model = "andestech,ax25";
+
+ aliases {
+ uart0 = &serial0;
+ spi0 = &spi;
+ } ;
+
+ chosen {
+ bootargs = "console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0xf0300000 debug loglevel=7";
+ stdout-path = "uart0:38400n8";
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <10000000>;
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ reg = <0>;
+ status = "okay";
+ compatible = "riscv";
+ riscv,isa = "rv64imafdc";
+ mmu-type = "riscv,sv39";
+ clock-frequency = <60000000>;
+ CPU0_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "riscv,cpu-intc";
+ };
+ };
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x00000000 0x0 0x40000000>;
+ };
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ compatible = "andestech,riscv-ae350-soc";
+ ranges;
+ };
+
+ plmt0@e6000000 {
+ compatible = "riscv,plmt0";
+ interrupts-extended = <&CPU0_intc 7>;
+ reg = <0x0 0xe6000000 0x0 0x100000>;
+ };
+
+ plic0: interrupt-controller@e4000000 {
+ compatible = "riscv,plic0";
+ #address-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ reg = <0x0 0xe4000000 0x0 0x2000000>;
+ riscv,ndev=<31>;
+ interrupts-extended = <&CPU0_intc 11 &CPU0_intc 9>;
+ };
+
+ plic1: interrupt-controller@e6400000 {
+ compatible = "riscv,plic1";
+ #address-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ reg = <0x0 0xe6400000 0x0 0x400000>;
+ riscv,ndev=<1>;
+ interrupts-extended = <&CPU0_intc 3>;
+ };
+
+ spiclk: virt_100mhz {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <100000000>;
+ };
+
+ timer0: timer@f0400000 {
+ compatible = "andestech,atcpit100";
+ reg = <0x0 0xf0400000 0x0 0x1000>;
+ clock-frequency = <40000000>;
+ interrupts = <3 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ serial0: serial@f0300000 {
+ compatible = "andestech,uart16550", "ns16550a";
+ reg = <0x0 0xf0300000 0x0 0x1000>;
+ interrupts = <9 4>;
+ clock-frequency = <19660800>;
+ reg-shift = <2>;
+ reg-offset = <32>;
+ no-loopback-test = <1>;
+ interrupt-parent = <&plic0>;
+ };
+
+ mac0: mac@e0100000 {
+ compatible = "andestech,atmac100";
+ reg = <0x0 0xe0100000 0x0 0x1000>;
+ interrupts = <19 4>;
+ interrupt-parent = <&plic0>;
+ };
+
+ mmc0: mmc@f0e00000 {
+ compatible = "andestech,atfsdc010";
+ max-frequency = <100000000>;
+ clock-freq-min-max = <400000 100000000>;
+ fifo-depth = <0x10>;
+ reg = <0x0 0xf0e00000 0x0 0x1000>;
+ interrupts = <18 4>;
+ cap-sd-highspeed;
+ interrupt-parent = <&plic0>;
+ };
+
+ smc0: smc@e0400000 {
+ compatible = "andestech,atfsmc020";
+ reg = <0x0 0xe0400000 0x0 0x1000>;
+ };
+
+ nor@0,0 {
+ compatible = "cfi-flash";
+ reg = <0x0 0x88000000 0x0 0x1000>;
+ bank-width = <2>;
+ device-width = <1>;
+ };
+
+ spi: spi@f0b00000 {
+ compatible = "andestech,atcspi200";
+ reg = <0x0 0xf0b00000 0x0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <1>;
+ clocks = <&spiclk>;
+ interrupts = <3 4>;
+ interrupt-parent = <&plic0>;
+ flash@0 {
+ compatible = "spi-flash";
+ spi-max-frequency = <50000000>;
+ reg = <0>;
+ spi-cpol;
+ spi-cpha;
+ };
+ };
+};
diff --git a/arch/riscv/include/asm/mach-types.h b/arch/riscv/include/asm/mach-types.h
index 93afff70b3..f219cedfd3 100644
--- a/arch/riscv/include/asm/mach-types.h
+++ b/arch/riscv/include/asm/mach-types.h
@@ -12,18 +12,18 @@
extern unsigned int __machine_arch_type;
#endif
-#define MACH_TYPE_AE250 1
+#define MACH_TYPE_AE350 1
-#ifdef CONFIG_ARCH_AE250
+#ifdef CONFIG_ARCH_AE350
# ifdef machine_arch_type
# undef machine_arch_type
# define machine_arch_type __machine_arch_type
# else
-# define machine_arch_type MACH_TYPE_AE250
+# define machine_arch_type MACH_TYPE_AE350
# endif
-# define machine_is_ae250() (machine_arch_type == MACH_TYPE_AE250)
+# define machine_is_ae350() (machine_arch_type == MACH_TYPE_AE350)
#else
-# define machine_is_ae250() (1)
+# define machine_is_ae350() (1)
#endif
#endif /* __ASM_RISCV_MACH_TYPE_H */
diff --git a/arch/riscv/include/asm/setjmp.h b/arch/riscv/include/asm/setjmp.h
new file mode 100644
index 0000000000..72383d4330
--- /dev/null
+++ b/arch/riscv/include/asm/setjmp.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018 Alexander Graf <agraf@suse.de>
+ */
+
+#ifndef _SETJMP_H_
+#define _SETJMP_H_ 1
+
+/*
+ * This really should be opaque, but the EFI implementation wrongly
+ * assumes that a 'struct jmp_buf_data' is defined.
+ */
+struct jmp_buf_data {
+ /* x2, x8, x9, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, sp */
+ unsigned long s_regs[12]; /* s0 - s11 */
+ unsigned long ra;
+ unsigned long sp;
+};
+
+typedef struct jmp_buf_data jmp_buf[1];
+
+int setjmp(jmp_buf jmp);
+void longjmp(jmp_buf jmp, int ret);
+
+#endif /* _SETJMP_H_ */
diff --git a/arch/riscv/include/asm/u-boot-riscv.h b/arch/riscv/include/asm/u-boot-riscv.h
index c4c068f9e2..49febd5881 100644
--- a/arch/riscv/include/asm/u-boot-riscv.h
+++ b/arch/riscv/include/asm/u-boot-riscv.h
@@ -16,5 +16,6 @@ int cleanup_before_linux(void);
/* board/.../... */
int board_init(void);
+void board_quiesce_devices(void);
#endif /* _U_BOOT_RISCV_H_ */
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 0b671f7086..cc562f935a 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -10,3 +10,15 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
obj-$(CONFIG_CMD_GO) += boot.o
obj-y += cache.o
obj-y += interrupts.o
+obj-y += setjmp.o
+
+# For building EFI apps
+CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI)
+CFLAGS_REMOVE_$(EFI_CRT0) := $(CFLAGS_NON_EFI)
+
+CFLAGS_$(EFI_RELOC) := $(CFLAGS_EFI)
+CFLAGS_REMOVE_$(EFI_RELOC) := $(CFLAGS_NON_EFI)
+
+extra-$(CONFIG_CMD_BOOTEFI_HELLO_COMPILE) += $(EFI_CRT0) $(EFI_RELOC)
+extra-$(CONFIG_CMD_BOOTEFI_SELFTEST) += $(EFI_CRT0) $(EFI_RELOC)
+extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c
index 8ede0485d4..2610a57bbf 100644
--- a/arch/riscv/lib/bootm.c
+++ b/arch/riscv/lib/bootm.c
@@ -15,6 +15,10 @@
DECLARE_GLOBAL_DATA_PTR;
+__weak void board_quiesce_devices(void)
+{
+}
+
int arch_fixup_fdt(void *blob)
{
return 0;
diff --git a/arch/riscv/lib/crt0_riscv_efi.S b/arch/riscv/lib/crt0_riscv_efi.S
new file mode 100644
index 0000000000..18f61f515a
--- /dev/null
+++ b/arch/riscv/lib/crt0_riscv_efi.S
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * crt0-efi-riscv.S - PE/COFF header for RISC-V EFI applications
+ *
+ * Copright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ * Copright (C) 2018 Alexander Graf <agraf@suse.de>
+ *
+ * This file is inspired by arch/arm/lib/crt0_aarch64_efi.S
+ */
+
+#include <asm-generic/pe.h>
+
+#if __riscv_xlen == 64
+#define SIZE_LONG 8
+#define SAVE_LONG(reg, idx) sd reg, (idx*SIZE_LONG)(sp)
+#define LOAD_LONG(reg, idx) ld reg, (idx*SIZE_LONG)(sp)
+#define PE_MACHINE 0x5064
+#else
+#define SIZE_LONG 4
+#define SAVE_LONG(reg, idx) sw reg, (idx*SIZE_LONG)(sp)
+#define LOAD_LONG(reg, idx) lw reg, (idx*SIZE_LONG)(sp)
+#define PE_MACHINE 0x5032
+#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 PE_MACHINE /* RISC-V 64/32-bit */
+ .short 2 /* nr_sections */
+ .long 0 /* TimeDateStamp */
+ .long 0 /* PointerToSymbolTable */
+ .long 1 /* NumberOfSymbols */
+ .short section_table - optional_header /* SizeOfOptionalHeader */
+ /*
+ * Characteristics: IMAGE_FILE_DEBUG_STRIPPED |
+ * IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED
+ */
+ .short 0x206
+optional_header:
+ .short 0x20b /* PE32+ format */
+ .byte 0x02 /* MajorLinkerVersion */
+ .byte 0x14 /* MinorLinkerVersion */
+ .long _edata - _start /* SizeOfCode */
+ .long 0 /* SizeOfInitializedData */
+ .long 0 /* SizeOfUninitializedData */
+ .long _start - ImageBase /* AddressOfEntryPoint */
+ .long _start - ImageBase /* BaseOfCode */
+
+extra_header_fields:
+ .quad 0 /* ImageBase */
+ .long 0x20 /* SectionAlignment */
+ .long 0x8 /* 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 IMAGE_SUBSYSTEM_EFI_APPLICATION /* 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"
+ .byte 0
+ .byte 0 /* end of 0 padding of section name */
+ .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"
+ .byte 0
+ .byte 0
+ .byte 0 /* end of 0 padding of section name */
+ .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) */
+
+_start:
+ addi sp, sp, -(SIZE_LONG * 3)
+ SAVE_LONG(a0, 0)
+ SAVE_LONG(a1, 1)
+ SAVE_LONG(ra, 2)
+
+ lla a0, ImageBase
+ lla a1, _DYNAMIC
+ call _relocate
+ bne a0, zero, 0f
+
+ LOAD_LONG(a1, 1)
+ LOAD_LONG(a0, 0)
+ call efi_main
+
+ LOAD_LONG(ra, 2)
+
+0: addi sp, sp, (SIZE_LONG * 3)
+ ret
diff --git a/arch/riscv/lib/elf_riscv32_efi.lds b/arch/riscv/lib/elf_riscv32_efi.lds
new file mode 100644
index 0000000000..629705fc28
--- /dev/null
+++ b/arch/riscv/lib/elf_riscv32_efi.lds
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * U-Boot riscv32 EFI linker script
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Modified from arch/arm/lib/elf_aarch64_efi.lds
+ */
+
+OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-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 : {
+ _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)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(16);
+ _bss_end = .;
+ _edata = .;
+ }
+ .rela.dyn : { *(.rela.dyn) }
+ .rela.plt : { *(.rela.plt) }
+ .rela.got : { *(.rela.got) }
+ .rela.data : { *(.rela.data) *(.rela.data*) }
+ _data_size = . - _etext;
+
+ . = 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) }
+}
diff --git a/arch/riscv/lib/elf_riscv64_efi.lds b/arch/riscv/lib/elf_riscv64_efi.lds
new file mode 100644
index 0000000000..aece030c37
--- /dev/null
+++ b/arch/riscv/lib/elf_riscv64_efi.lds
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * U-Boot riscv64 EFI linker script
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Modified from arch/arm/lib/elf_aarch64_efi.lds
+ */
+
+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 : {
+ _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)
+ *(.bss.*)
+ *(COMMON)
+ . = ALIGN(16);
+ _bss_end = .;
+ _edata = .;
+ }
+ .rela.dyn : { *(.rela.dyn) }
+ .rela.plt : { *(.rela.plt) }
+ .rela.got : { *(.rela.got) }
+ .rela.data : { *(.rela.data) *(.rela.data*) }
+ _data_size = . - _etext;
+
+ . = 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) }
+}
diff --git a/arch/riscv/lib/reloc_riscv_efi.c b/arch/riscv/lib/reloc_riscv_efi.c
new file mode 100644
index 0000000000..8b4b2b1d8f
--- /dev/null
+++ b/arch/riscv/lib/reloc_riscv_efi.c
@@ -0,0 +1,98 @@
+// 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>
+
+#if __riscv_xlen == 64
+#define Elf_Dyn Elf64_Dyn
+#define Elf_Rela Elf64_Rela
+#define ELF_R_TYPE ELF64_R_TYPE
+#else
+#define Elf_Dyn Elf32_Dyn
+#define Elf_Rela Elf32_Rela
+#define ELF_R_TYPE ELF32_R_TYPE
+#endif
+
+efi_status_t _relocate(long ldbase, Elf_Dyn *dyn, efi_handle_t image,
+ struct efi_system_table *systab)
+{
+ long relsz = 0, relent = 0;
+ Elf_Rela *rel = 0;
+ 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 *)((ulong)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 = (ulong *)(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;
+}
diff --git a/arch/riscv/lib/setjmp.S b/arch/riscv/lib/setjmp.S
new file mode 100644
index 0000000000..8f5a6a23aa
--- /dev/null
+++ b/arch/riscv/lib/setjmp.S
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) 2018 Alexander Graf <agraf@suse.de>
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+
+#ifdef CONFIG_CPU_RISCV_64
+#define STORE_IDX(reg, idx) sd reg, (idx*8)(a0)
+#define LOAD_IDX(reg, idx) ld reg, (idx*8)(a0)
+#else
+#define STORE_IDX(reg, idx) sw reg, (idx*4)(a0)
+#define LOAD_IDX(reg, idx) lw reg, (idx*4)(a0)
+#endif
+
+.pushsection .text.setjmp, "ax"
+ENTRY(setjmp)
+ /* Preserve all callee-saved registers and the SP */
+ STORE_IDX(s0, 0)
+ STORE_IDX(s1, 1)
+ STORE_IDX(s2, 2)
+ STORE_IDX(s3, 3)
+ STORE_IDX(s4, 4)
+ STORE_IDX(s5, 5)
+ STORE_IDX(s6, 6)
+ STORE_IDX(s7, 7)
+ STORE_IDX(s8, 8)
+ STORE_IDX(s9, 9)
+ STORE_IDX(s10, 10)
+ STORE_IDX(s11, 11)
+ STORE_IDX(ra, 12)
+ STORE_IDX(sp, 13)
+ li a0, 0
+ ret
+ENDPROC(setjmp)
+.popsection
+
+.pushsection .text.longjmp, "ax"
+ENTRY(longjmp)
+ LOAD_IDX(s0, 0)
+ LOAD_IDX(s1, 1)
+ LOAD_IDX(s2, 2)
+ LOAD_IDX(s3, 3)
+ LOAD_IDX(s4, 4)
+ LOAD_IDX(s5, 5)
+ LOAD_IDX(s6, 6)
+ LOAD_IDX(s7, 7)
+ LOAD_IDX(s8, 8)
+ LOAD_IDX(s9, 9)
+ LOAD_IDX(s10, 10)
+ LOAD_IDX(s11, 11)
+ LOAD_IDX(ra, 12)
+ LOAD_IDX(sp, 13)
+
+ /* Move the return value in place, but return 1 if passed 0. */
+ beq a1, zero, longjmp_1
+ mv a0, a1
+ ret
+
+ longjmp_1:
+ li a0, 1
+ ret
+ENDPROC(longjmp)
+.popsection