RISC-V boot1.efi and loader.efi support
This implementation doesn't have any major deviations from the other EFI ports. I've copied the boilerplate from arm and arm64. I've tested this with the following boot flows: OpenSBI (M-mode) -> u-boot (S-mode) -> loader.efi -> FreeBSD OpenSBI (M-mode) -> u-boot (S-mode) -> boot1.efi -> loader.efi -> FreeBSD Due to the way that u-boot handles secondary CPUs, OpenSBI >= v0.7 is required, as the HSM extension is needed to bring them up explicitly. Because of this, using BBL as the SBI implementation will not be possible. Additionally, there are a few recent u-boot changes that are required as well, all of which will be present in the upcoming v2020.07 release. Looks good: emaste Differential Revision: https://reviews.freebsd.org/D25135
This commit is contained in:
parent
10aabc8b83
commit
2192efc03b
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
217
stand/efi/include/riscv/efibind.h
Normal file
217
stand/efi/include/riscv/efibind.h
Normal file
@ -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
|
@ -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
|
||||
|
||||
|
7
stand/efi/loader/arch/riscv/Makefile.inc
Normal file
7
stand/efi/loader/arch/riscv/Makefile.inc
Normal file
@ -0,0 +1,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
HAVE_FDT=yes
|
||||
|
||||
SRCS+= exec.c \
|
||||
efiserialio.c \
|
||||
start.S
|
92
stand/efi/loader/arch/riscv/exec.c
Normal file
92
stand/efi/loader/arch/riscv/exec.c
Normal file
@ -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
|
||||
};
|
87
stand/efi/loader/arch/riscv/ldscript.riscv
Normal file
87
stand/efi/loader/arch/riscv/ldscript.riscv
Normal file
@ -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) }
|
||||
}
|
168
stand/efi/loader/arch/riscv/start.S
Normal file
168
stand/efi/loader/arch/riscv/start.S
Normal file
@ -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
|
@ -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 @@ efi_check_space(vm_offset_t end)
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -31,5 +31,27 @@
|
||||
#define _MACHINE_METADATA_H_
|
||||
|
||||
#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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user