aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/mk/src.opts.mk4
-rw-r--r--stand/common/self_reloc.c5
-rw-r--r--stand/defs.mk13
-rw-r--r--stand/efi/include/riscv/efibind.h217
-rw-r--r--stand/efi/libefi/Makefile3
-rw-r--r--stand/efi/loader/arch/riscv/Makefile.inc7
-rw-r--r--stand/efi/loader/arch/riscv/exec.c92
-rw-r--r--stand/efi/loader/arch/riscv/ldscript.riscv87
-rw-r--r--stand/efi/loader/arch/riscv/start.S168
-rw-r--r--stand/efi/loader/copy.c9
-rw-r--r--stand/efi/loader/main.c2
-rw-r--r--stand/loader.mk3
-rw-r--r--sys/riscv/include/metadata.h24
13 files changed, 623 insertions, 11 deletions
diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
index 379bdebfe31c..e596f216c258 100644
--- a/share/mk/src.opts.mk
+++ b/share/mk/src.opts.mk
@@ -318,8 +318,8 @@ BROKEN_OPTIONS+=LIBSOFT
# marked no longer broken with the switch to LLVM.
BROKEN_OPTIONS+=GOOGLETEST SSP
.endif
-# EFI doesn't exist on mips, powerpc, or riscv.
-.if ${__T:Mmips*} || ${__T:Mpowerpc*} || ${__T:Mriscv*}
+# EFI doesn't exist on mips or powerpc.
+.if ${__T:Mmips*} || ${__T:Mpowerpc*}
BROKEN_OPTIONS+=EFI
.endif
# OFW is only for powerpc, exclude others
diff --git a/stand/common/self_reloc.c b/stand/common/self_reloc.c
index 5f6bfcbb27bb..aee19cd8c574 100644
--- a/stand/common/self_reloc.c
+++ b/stand/common/self_reloc.c
@@ -31,7 +31,7 @@ __FBSDID("$FreeBSD$");
#include <elf.h>
#include <bootstrap.h>
-#if defined(__aarch64__) || defined(__amd64__)
+#if defined(__aarch64__) || defined(__amd64__) || defined(__riscv)
#define ElfW_Rel Elf64_Rela
#define ElfW_Dyn Elf64_Dyn
#define ELFW_R_TYPE ELF64_R_TYPE
@@ -55,6 +55,9 @@ __FBSDID("$FreeBSD$");
#elif defined(__i386__)
#define RELOC_TYPE_NONE R_386_NONE
#define RELOC_TYPE_RELATIVE R_386_RELATIVE
+#elif defined(__riscv)
+#define RELOC_TYPE_NONE R_RISCV_NONE
+#define RELOC_TYPE_RELATIVE R_RISCV_RELATIVE
#endif
void self_reloc(Elf_Addr baseaddr, ElfW_Dyn *dynamic);
diff --git a/stand/defs.mk b/stand/defs.mk
index 776da61e66cc..a36bfb9acfa8 100644
--- a/stand/defs.mk
+++ b/stand/defs.mk
@@ -115,13 +115,14 @@ AFLAGS+= --32
SSP_CFLAGS=
# Add in the no float / no SIMD stuff and announce we're freestanding
-# aarch64 and riscv don't have -msoft-float, but all others do. riscv
-# currently has no /boot/loader, but may soon.
+# aarch64 and riscv don't have -msoft-float, but all others do.
CFLAGS+= -ffreestanding ${CFLAGS_NO_SIMD}
.if ${MACHINE_CPUARCH} == "aarch64"
CFLAGS+= -mgeneral-regs-only -ffixed-x18 -fPIC
.elif ${MACHINE_CPUARCH} == "riscv"
-CFLAGS+= -march=rv64imac -mabi=lp64
+CFLAGS+= -march=rv64imac -mabi=lp64 -fPIC
+CFLAGS.clang+= -mcmodel=medium
+CFLAGS.gcc+= -mcmodel=medany
.else
CFLAGS+= -msoft-float
.endif
@@ -148,6 +149,12 @@ CFLAGS.clang+= -mfpu=none
CFLAGS+= -fPIC
.endif
+# Some RISC-V linkers have support for relaxations, while some (lld) do not
+# yet. If this is the case we inhibit the compiler from emitting relaxations.
+.if ${LINKER_FEATURES:Mriscv-relaxations} == ""
+CFLAGS+= -mno-relax
+.endif
+
# The boot loader build uses dd status=none, where possible, for reproducible
# build output (since performance varies from run to run). Trouble is that
# option was recently (10.3) added to FreeBSD and is non-standard. Only use it
diff --git a/stand/efi/include/riscv/efibind.h b/stand/efi/include/riscv/efibind.h
new file mode 100644
index 000000000000..4751e2e944a8
--- /dev/null
+++ b/stand/efi/include/riscv/efibind.h
@@ -0,0 +1,217 @@
+/* $FreeBSD$ */
+/*++
+
+Copyright (c) 1999 - 2003 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ efefind.h
+
+Abstract:
+
+ EFI to compile bindings
+
+
+
+
+Revision History
+
+--*/
+
+#pragma pack()
+
+
+#ifdef __FreeBSD__
+#include <sys/stdint.h>
+#else
+//
+// Basic int types of various widths
+//
+
+#if (__STDC_VERSION__ < 199901L )
+
+ // No ANSI C 1999/2000 stdint.h integer width declarations
+
+ #ifdef _MSC_EXTENSIONS
+
+ // Use Microsoft C compiler integer width declarations
+
+ typedef unsigned __int64 uint64_t;
+ typedef __int64 int64_t;
+ typedef unsigned __int32 uint32_t;
+ typedef __int32 int32_t;
+ typedef unsigned __int16 uint16_t;
+ typedef __int16 int16_t;
+ typedef unsigned __int8 uint8_t;
+ typedef __int8 int8_t;
+ #else
+ #ifdef UNIX_LP64
+
+ // Use LP64 programming model from C_FLAGS for integer width declarations
+
+ typedef unsigned long uint64_t;
+ typedef long int64_t;
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #else
+
+ // Assume P64 programming model from C_FLAGS for integer width declarations
+
+ typedef unsigned long long uint64_t;
+ typedef long long int64_t;
+ typedef unsigned int uint32_t;
+ typedef int int32_t;
+ typedef unsigned short uint16_t;
+ typedef short int16_t;
+ typedef unsigned char uint8_t;
+ typedef char int8_t;
+ #endif
+ #endif
+#endif
+#endif /* __FreeBSD__ */
+
+//
+// Basic EFI types of various widths
+//
+
+
+typedef uint64_t UINT64;
+typedef int64_t INT64;
+typedef uint32_t UINT32;
+typedef int32_t INT32;
+typedef uint16_t UINT16;
+typedef int16_t INT16;
+typedef uint8_t UINT8;
+typedef int8_t INT8;
+
+
+#undef VOID
+#define VOID void
+
+
+typedef int64_t INTN;
+typedef uint64_t UINTN;
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// BugBug: Code to debug
+//
+#define BIT63 0x8000000000000000
+
+#define PLATFORM_IOBASE_ADDRESS (0xffffc000000 | BIT63)
+#define PORT_TO_MEMD(_Port) (PLATFORM_IOBASE_ADDRESS | ( ( ( (_Port) & 0xfffc) << 10 ) | ( (_Port) & 0x0fff) ) )
+
+//
+// Macro's with casts make this much easier to use and read.
+//
+#define PORT_TO_MEM8D(_Port) (*(UINT8 *)(PORT_TO_MEMD(_Port)))
+#define POST_CODE(_Data) (PORT_TO_MEM8D(0x80) = (_Data))
+//
+// BugBug: End Debug Code!!!
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#define EFIERR(a) (0x8000000000000000 | a)
+#define EFI_ERROR_MASK 0x8000000000000000
+#define EFIERR_OEM(a) (0xc000000000000000 | a)
+
+#define BAD_POINTER 0xFBFBFBFBFBFBFBFB
+#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF
+
+#define BREAKPOINT() __break(0)
+
+//
+// Pointers must be aligned to these address to function
+// you will get an alignment fault if this value is less than 8
+//
+#define MIN_ALIGNMENT_SIZE 8
+
+#define ALIGN_VARIABLE(Value , Adjustment) \
+ (UINTN) Adjustment = 0; \
+ if((UINTN)Value % MIN_ALIGNMENT_SIZE) \
+ (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \
+ Value = (UINTN)Value + (UINTN)Adjustment
+
+//
+// Define macros to create data structure signatures.
+//
+
+#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))
+
+//
+// EFIAPI - prototype calling convention for EFI function pointers
+// BOOTSERVICE - prototype for implementation of a boot service interface
+// RUNTIMESERVICE - prototype for implementation of a runtime service interface
+// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service
+// RUNTIME_CODE - pragma macro for declaring runtime code
+//
+
+#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options
+ #ifdef _MSC_EXTENSIONS
+ #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler
+ #else
+ #define EFIAPI // Substitute expresion to force C calling convention
+ #endif
+#endif
+
+#define BOOTSERVICE
+#define RUNTIMESERVICE
+#define RUNTIMEFUNCTION
+
+#define RUNTIME_CODE(a) alloc_text("rtcode", a)
+#define BEGIN_RUNTIME_DATA() data_seg("rtdata")
+#define END_RUNTIME_DATA() data_seg()
+
+#define VOLATILE volatile
+
+//
+// BugBug: Need to find out if this is portable across compilers.
+//
+void __mfa (void);
+#define MEMORY_FENCE() __mfa()
+
+#ifdef EFI_NO_INTERFACE_DECL
+ #define EFI_FORWARD_DECLARATION(x)
+ #define EFI_INTERFACE_DECL(x)
+#else
+ #define EFI_FORWARD_DECLARATION(x) typedef struct _##x x
+ #define EFI_INTERFACE_DECL(x) typedef struct x
+#endif
+
+//
+// When build similar to FW, then link everything together as
+// one big module.
+//
+
+#define EFI_DRIVER_ENTRY_POINT(InitFunction)
+
+#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \
+ (_if)->LoadInternal(type, name, entry)
+// entry(NULL, ST)
+
+#ifdef __FreeBSD__
+#define INTERFACE_DECL(x) struct x
+#else
+//
+// Some compilers don't support the forward reference construct:
+// typedef struct XXXXX
+//
+// The following macro provide a workaround for such cases.
+//
+#ifdef NO_INTERFACE_DECL
+#define INTERFACE_DECL(x)
+#else
+#define INTERFACE_DECL(x) typedef struct x
+#endif
+#endif
diff --git a/stand/efi/libefi/Makefile b/stand/efi/libefi/Makefile
index 8bbd421486ca..8006893d0cbe 100644
--- a/stand/efi/libefi/Makefile
+++ b/stand/efi/libefi/Makefile
@@ -27,7 +27,8 @@ SRCS+= teken.c
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
SRCS+= time.c
-.elif ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
+.elif ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm" || \
+ ${MACHINE_CPUARCH} == "riscv"
SRCS+= time_event.c
.endif
diff --git a/stand/efi/loader/arch/riscv/Makefile.inc b/stand/efi/loader/arch/riscv/Makefile.inc
new file mode 100644
index 000000000000..333b789e935d
--- /dev/null
+++ b/stand/efi/loader/arch/riscv/Makefile.inc
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+HAVE_FDT=yes
+
+SRCS+= exec.c \
+ efiserialio.c \
+ start.S
diff --git a/stand/efi/loader/arch/riscv/exec.c b/stand/efi/loader/arch/riscv/exec.c
new file mode 100644
index 000000000000..7803932184cd
--- /dev/null
+++ b/stand/efi/loader/arch/riscv/exec.c
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2001 Benno Rice <benno@FreeBSD.org>
+ * Copyright (c) 2007 Semihalf, Rafal Jaworowski <raj@semihalf.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:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/linker.h>
+
+#include <machine/md_var.h>
+#include <machine/metadata.h>
+#include <machine/elf.h>
+
+#include <stand.h>
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "bootstrap.h"
+#include "loader_efi.h"
+
+extern int bi_load(char *, vm_offset_t *, vm_offset_t *);
+
+static int
+__elfN(exec)(struct preloaded_file *fp)
+{
+ struct file_metadata *fmp;
+ vm_offset_t modulep, kernend;
+ Elf_Ehdr *e;
+ int error;
+ void (*entry)(void *);
+
+ if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL)
+ return (EFTYPE);
+
+ e = (Elf_Ehdr *)&fmp->md_data;
+
+ efi_time_fini();
+
+ entry = efi_translate(e->e_entry);
+
+ printf("Kernel entry at 0x%x...\n", (unsigned)entry);
+ printf("Kernel args: %s\n", fp->f_args);
+
+ if ((error = bi_load(fp->f_args, &modulep, &kernend)) != 0) {
+ efi_time_init();
+ return (error);
+ }
+
+ /*
+ * At this point we've called ExitBootServices, so we can't call
+ * printf or any other function that uses Boot Services
+ */
+ dev_cleanup();
+
+ (*entry)((void *)modulep);
+ panic("exec returned");
+}
+
+static struct file_format riscv_elf = {
+ __elfN(loadfile),
+ __elfN(exec)
+};
+
+struct file_format *file_formats[] = {
+ &riscv_elf,
+ NULL
+};
diff --git a/stand/efi/loader/arch/riscv/ldscript.riscv b/stand/efi/loader/arch/riscv/ldscript.riscv
new file mode 100644
index 000000000000..722c5fa360fa
--- /dev/null
+++ b/stand/efi/loader/arch/riscv/ldscript.riscv
@@ -0,0 +1,87 @@
+/* $FreeBSD$ */
+OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv")
+OUTPUT_ARCH(riscv64)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0;
+ ImageBase = .;
+ .text : {
+ *(.peheader)
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.plt)
+ } =0x9090
+ . = ALIGN(16);
+ .data : {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.rodata1)
+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+ *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
+ *(.opd)
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.data1)
+ *(.plabel)
+
+ . = ALIGN(16);
+ __bss_start = .;
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss *.bss.*)
+ *(COMMON)
+ . = ALIGN(16);
+ __bss_end = .;
+ }
+ . = ALIGN(16);
+ set_Xcommand_set : {
+ __start_set_Xcommand_set = .;
+ *(set_Xcommand_set)
+ __stop_set_Xcommand_set = .;
+ }
+ set_Xficl_compile_set : {
+ __start_set_Xficl_compile_set = .;
+ *(set_Xficl_compile_set)
+ __stop_set_Xficl_compile_set = .;
+ }
+ . = ALIGN(16);
+ .sdata : {
+ /*
+ * u-boot expects the gp register to be untouched by the EFI payload, so we
+ * can't enable this yet.
+ */
+ /* __global_pointer$ = . + 0x800; */
+ *(.got.plt .got)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ *(dynsbss)
+ *(.scommon)
+ }
+ . = ALIGN(16);
+ .dynamic : { *(.dynamic) }
+ . = ALIGN(16);
+ .rela.dyn : {
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.got)
+ *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
+ *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
+ *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
+ *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ *(.rela.plt)
+ *(.relset_*)
+ *(.rela.dyn .rela.dyn.*)
+ }
+ . = ALIGN(16);
+ .reloc : { *(.reloc) }
+ . = ALIGN(16);
+ .dynsym : { *(.dynsym) }
+ _edata = .;
+
+ /* Unused sections */
+ .dynstr : { *(.dynstr) }
+ .hash : { *(.hash) }
+}
diff --git a/stand/efi/loader/arch/riscv/start.S b/stand/efi/loader/arch/riscv/start.S
new file mode 100644
index 000000000000..e63ce68d86ba
--- /dev/null
+++ b/stand/efi/loader/arch/riscv/start.S
@@ -0,0 +1,168 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Mitchell Horne <mhorne@FreeBSD.org>
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asm.h>
+
+/*
+ * We need to be a PE32+ file for EFI. On some architectures we can use
+ * objcopy to create the correct file, however on RISC-V we need to do
+ * it ourselves.
+ */
+
+#define IMAGE_FILE_MACHINE_RISCV64 0x5064
+
+#define IMAGE_SCN_CNT_CODE 0x00000020
+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+#define IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define IMAGE_SCN_MEM_READ 0x40000000
+
+ .section .peheader,"a"
+efi_start:
+ /* The MS-DOS Stub, only used to get the offset of the COFF header */
+ .ascii "MZ"
+ .short 0
+ .space 0x38
+ .long pe_sig - efi_start
+
+ /* The PE32 Signature. Needs to be 8-byte aligned */
+ .align 3
+pe_sig:
+ .ascii "PE"
+ .short 0
+coff_head:
+ .short IMAGE_FILE_MACHINE_RISCV64 /* RISC-V 64 file */
+ .short 2 /* 2 Sections */
+ .long 0 /* Timestamp */
+ .long 0 /* No symbol table */
+ .long 0 /* No symbols */
+ .short section_table - optional_header /* Optional header size */
+ .short 0 /* Characteristics TODO: Fill in */
+
+optional_header:
+ .short 0x020b /* PE32+ (64-bit addressing) */
+ .byte 0 /* Major linker version */
+ .byte 0 /* Minor linker version */
+ .long _edata - _end_header /* Code size */
+ .long 0 /* No initialized data */
+ .long 0 /* No uninitialized data */
+ .long _start - efi_start /* Entry point */
+ .long _end_header - efi_start /* Start of code */
+
+optional_windows_header:
+ .quad 0 /* Image base */
+ .long 32 /* Section Alignment */
+ .long 8 /* File alignment */
+ .short 0 /* Major OS version */
+ .short 0 /* Minor OS version */
+ .short 0 /* Major image version */
+ .short 0 /* Minor image version */
+ .short 0 /* Major subsystem version */
+ .short 0 /* Minor subsystem version */
+ .long 0 /* Win32 version */
+ .long _edata - efi_start /* Image size */
+ .long _end_header - efi_start /* Header size */
+ .long 0 /* Checksum */
+ .short 0xa /* Subsystem (EFI app) */
+ .short 0 /* DLL Characteristics */
+ .quad 0 /* Stack reserve */
+ .quad 0 /* Stack commit */
+ .quad 0 /* Heap reserve */
+ .quad 0 /* Heap commit */
+ .long 0 /* Loader flags */
+ .long 6 /* Number of RVAs */
+
+ /* RVAs: */
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+ .quad 0
+
+section_table:
+ /* We need a .reloc section for EFI */
+ .ascii ".reloc"
+ .byte 0
+ .byte 0 /* Pad to 8 bytes */
+ .long 0 /* Virtual size */
+ .long 0 /* Virtual address */
+ .long 0 /* Size of raw data */
+ .long 0 /* Pointer to raw data */
+ .long 0 /* Pointer to relocations */
+ .long 0 /* Pointer to line numbers */
+ .short 0 /* Number of relocations */
+ .short 0 /* Number of line numbers */
+ .long (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | \
+ IMAGE_SCN_MEM_DISCARDABLE) /* Characteristics */
+
+ /* The contents of the loader */
+ .ascii ".text"
+ .byte 0
+ .byte 0
+ .byte 0 /* Pad to 8 bytes */
+ .long _edata - _end_header /* Virtual size */
+ .long _end_header - efi_start /* Virtual address */
+ .long _edata - _end_header /* Size of raw data */
+ .long _end_header - efi_start /* Pointer to raw data */
+ .long 0 /* Pointer to relocations */
+ .long 0 /* Pointer to line numbers */
+ .short 0 /* Number of relocations */
+ .short 0 /* Number of line numbers */
+ .long (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | \
+ IMAGE_SCN_MEM_READ) /* Characteristics */
+_end_header:
+
+ .text
+ .globl _start
+_start:
+ /* Save the boot params to the stack */
+ addi sp, sp, -16
+ sd a0, 0(sp)
+ sd a1, 8(sp)
+
+ /* Zero the BSS */
+ lla t0, __bss_start
+ lla t1, __bss_end
+
+1: sd zero, 0(t0)
+ addi t0, t0, 8
+ bltu t0, t1, 1b
+
+ lla a0, ImageBase
+ lla a1, _DYNAMIC
+ call _C_LABEL(self_reloc)
+
+ ld a1, 8(sp)
+ ld a0, 0(sp)
+ tail _C_LABEL(efi_main)
+
+ /* NOTREACHED */
+2: wfi
+ j 2b
diff --git a/stand/efi/loader/copy.c b/stand/efi/loader/copy.c
index 6499a44b9bbe..f4887df11e5c 100644
--- a/stand/efi/loader/copy.c
+++ b/stand/efi/loader/copy.c
@@ -227,7 +227,7 @@ efi_copy_init(void)
staging_base = staging;
staging_end = staging + nr_pages * EFI_PAGE_SIZE;
-#if defined(__aarch64__) || defined(__arm__)
+#if defined(__aarch64__) || defined(__arm__) || defined(__riscv)
/*
* Round the kernel load address to a 2MiB value. This is needed
* because the kernel builds a page table based on where it has
@@ -277,7 +277,7 @@ before_staging:
return (false);
}
addr = staging - nr_pages * EFI_PAGE_SIZE;
-#if defined(__aarch64__) || defined(__arm__)
+#if defined(__aarch64__) || defined(__arm__) || defined(__riscv)
/* See efi_copy_init for why this is needed */
addr = rounddown2(addr, 2 * 1024 * 1024);
#endif
@@ -344,6 +344,11 @@ ssize_t
efi_readin(readin_handle_t fd, vm_offset_t dest, const size_t len)
{
+ if (!stage_offset_set) {
+ stage_offset = (vm_offset_t)staging - dest;
+ stage_offset_set = 1;
+ }
+
if (!efi_check_space(dest + stage_offset + len)) {
errno = ENOMEM;
return (-1);
diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c
index 6ad626b2df39..8ba03141c95b 100644
--- a/stand/efi/loader/main.c
+++ b/stand/efi/loader/main.c
@@ -912,7 +912,7 @@ main(int argc, CHAR16 *argv[])
*/
setenv("console", "efi", 1);
uhowto = parse_uefi_con_out();
-#if defined(__aarch64__) || defined(__arm__)
+#if defined(__aarch64__) || defined(__arm__) || defined(__riscv)
if ((uhowto & RB_SERIAL) != 0)
setenv("console", "comconsole", 1);
#endif
diff --git a/stand/loader.mk b/stand/loader.mk
index 64033f11720f..59fcb568c22c 100644
--- a/stand/loader.mk
+++ b/stand/loader.mk
@@ -25,6 +25,9 @@ SRCS+= metadata.c
.elif ${MACHINE} == "mips"
SRCS+= load_elf32.c reloc_elf32.c
SRCS+= metadata.c
+.elif ${MACHINE_CPUARCH} == "riscv"
+SRCS+= load_elf64.c reloc_elf64.c
+SRCS+= metadata.c
.endif
.if ${LOADER_DISK_SUPPORT:Uyes} == "yes"
diff --git a/sys/riscv/include/metadata.h b/sys/riscv/include/metadata.h
index 2d9d82421636..520b7b6fca3a 100644
--- a/sys/riscv/include/metadata.h
+++ b/sys/riscv/include/metadata.h
@@ -30,6 +30,28 @@
#ifndef _MACHINE_METADATA_H_
#define _MACHINE_METADATA_H_
-#define MODINFOMD_DTBP 0x1001
+#define MODINFOMD_DTBP 0x1001
+#define MODINFOMD_EFI_MAP 0x1002
+
+struct efi_map_header {
+ size_t memory_size;
+ size_t descriptor_size;
+ uint32_t descriptor_version;
+};
+
+/*
+ * Placeholder for now
+ */
+struct efi_fb {
+ uint64_t fb_addr;
+ uint64_t fb_size;
+ uint32_t fb_height;
+ uint32_t fb_width;
+ uint32_t fb_stride;
+ uint32_t fb_mask_red;
+ uint32_t fb_mask_green;
+ uint32_t fb_mask_blue;
+ uint32_t fb_mask_reserved;
+};
#endif /* !_MACHINE_METADATA_H_ */