diff options
Diffstat (limited to 'arch/riscv')
-rw-r--r-- | arch/riscv/Kconfig | 6 | ||||
-rw-r--r-- | arch/riscv/config.mk | 7 | ||||
-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/Makefile | 2 | ||||
-rw-r--r-- | arch/riscv/dts/ae250.dts | 97 | ||||
-rw-r--r-- | arch/riscv/dts/ae350.dts | 149 | ||||
-rw-r--r-- | arch/riscv/include/asm/mach-types.h | 10 | ||||
-rw-r--r-- | arch/riscv/include/asm/setjmp.h | 25 | ||||
-rw-r--r-- | arch/riscv/include/asm/u-boot-riscv.h | 1 | ||||
-rw-r--r-- | arch/riscv/lib/Makefile | 12 | ||||
-rw-r--r-- | arch/riscv/lib/bootm.c | 4 | ||||
-rw-r--r-- | arch/riscv/lib/crt0_riscv_efi.S | 151 | ||||
-rw-r--r-- | arch/riscv/lib/elf_riscv32_efi.lds | 71 | ||||
-rw-r--r-- | arch/riscv/lib/elf_riscv64_efi.lds | 71 | ||||
-rw-r--r-- | arch/riscv/lib/reloc_riscv_efi.c | 98 | ||||
-rw-r--r-- | arch/riscv/lib/setjmp.S | 65 |
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 |