Compare commits

...

4 Commits

Author SHA1 Message Date
8fc11d8a4a [build] Allow for per-architecture cross-compilation prefixes
We currently require the variable CROSS (or CROSS_COMPILE) to be set
to specify the global cross-compilation prefix.  This becomes
cumbersome when developing across multiple CPU architectures,
requiring frequent editing of build command lines and preventing
incompatible architectures from being built with a single command.

Allow a default cross-compilation prefix for each architecture to be
specified via the CROSS_COMPILE_<arch> variables.  These may then be
provided as environment variables, e.g. using

  export CROSS_COMPILE_arm32=arm-linux-gnu-
  export CROSS_COMPILE_arm64=aarch64-linux-gnu-
  export CROSS_COMPILE_loong64=loongarch64-linux-gnu-
  export CROSS_COMPILE_riscv32=riscv64-linux-gnu-
  export CROSS_COMPILE_riscv64=riscv64-linux-gnu-

This change requires some portions of the Makefile to be rearranged,
to allow for the fact that $(CROSS_COMPILE) may not have been set
until the build directory has been parsed to determine the CPU
architecture.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-29 14:11:08 +00:00
19f44d2998 [riscv] Check if seed CSR is accessible from S-mode
The seed CSR defined by the Zkr extension is accessible only in M-mode
by default.  Older versions of OpenSBI (prior to version 1.4) do not
set mseccfg.sseed, with the result that attempts to access the seed
CSR from S-mode will raise an illegal instruction exception.

Add a facility for testing the accessibility of arbitrary CSRs, and
use it to check that the seed CSR is accessible before reporting the
seed CSR entropy source as being functional.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 23:07:14 +00:00
e0e102ee24 [sbi] Add support for running as a RISC-V SBI payload
Add basic support for running directly on top of SBI, with no UEFI
firmware present.  Build as e.g.:

  make CROSS=riscv64-linux-gnu- bin-riscv64/ipxe.sbi

The resulting binary can be tested in QEMU using e.g.:

  qemu-system-riscv64 -M virt -cpu max -serial stdio \
                      -kernel bin-riscv64/ipxe.sbi

No drivers or executable binary formats are supported yet, but the
unit test suite may be run successfully.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 19:20:50 +00:00
7ccd08dbf4 [build] Allow default platform to vary by architecture
Restructure the parsing of the build directory name from

  bin[[-<arch>]-<platform>]

to

  bin[-<arch>[-<platform>]]

and allow for a per-architecture default build platform.

For the sake of backwards compatibility, handle "bin-efi" as a special
case equivalent to "bin-i386-efi".

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2024-10-28 18:34:55 +00:00
19 changed files with 765 additions and 133 deletions

View File

@ -26,16 +26,16 @@ PRINTF := printf
PERL := perl
PYTHON := python
TRUE := true
CC := $(CROSS_COMPILE)gcc
CPP := $(CC) -E
AS := $(CROSS_COMPILE)as
LD := $(CROSS_COMPILE)ld
SIZE := $(CROSS_COMPILE)size
AR := $(CROSS_COMPILE)ar
RANLIB := $(CROSS_COMPILE)ranlib
OBJCOPY := $(CROSS_COMPILE)objcopy
NM := $(CROSS_COMPILE)nm
OBJDUMP := $(CROSS_COMPILE)objdump
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
SIZE = $(CROSS_COMPILE)size
AR = $(CROSS_COMPILE)ar
RANLIB = $(CROSS_COMPILE)ranlib
OBJCOPY = $(CROSS_COMPILE)objcopy
NM = $(CROSS_COMPILE)nm
OBJDUMP = $(CROSS_COMPILE)objdump
OPENSSL := openssl
CSPLIT := csplit
PARSEROM := ./util/parserom.pl

View File

@ -3,6 +3,20 @@
# This file contains various boring housekeeping functions that would
# otherwise seriously clutter up the main Makefile.
###############################################################################
#
# Make syntax does not allow use of comma or space in certain places.
# This ugly workaround is suggested in the manual.
#
COMMA := ,
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
HASH := \#
define NEWLINE
endef
###############################################################################
#
# Find a usable "echo -e" substitute.
@ -68,56 +82,6 @@ HOST_OS := $(shell uname -s)
hostos :
@$(ECHO) $(HOST_OS)
###############################################################################
#
# Determine compiler
CCDEFS := $(shell $(CC) -E -x c -c /dev/null -dM | cut -d" " -f2)
ccdefs:
@$(ECHO) $(CCDEFS)
ifeq ($(filter __GNUC__,$(CCDEFS)),__GNUC__)
CCTYPE := gcc
endif
cctype:
@$(ECHO) $(CCTYPE)
###############################################################################
#
# Check for tools that can cause failed builds
#
ifeq ($(CCTYPE),gcc)
GCC_2_96_BANNER := $(shell $(CC) -v 2>&1 | grep -is 'gcc version 2\.96')
ifneq ($(GCC_2_96_BANNER),)
$(warning gcc 2.96 is unsuitable for compiling iPXE)
$(warning Use gcc 2.95 or a newer version instead)
$(error Unsuitable build environment found)
endif
endif
PERL_UNICODE_CHECK := $(shell $(PERL) -e 'use bytes; print chr(255)' | wc -c)
ifeq ($(PERL_UNICODE_CHECK),2)
$(warning Your Perl version has a Unicode handling bug)
$(warning Execute this command before building iPXE:)
$(warning export LANG=$${LANG%.UTF-8})
$(error Unsuitable build environment found)
endif
LD_GOLD_BANNER := $(shell $(LD) -v 2>&1 | grep 'GNU gold')
ifneq ($(LD_GOLD_BANNER),)
$(warning GNU gold is unsuitable for building iPXE)
$(warning Use GNU ld instead)
$(error Unsuitable build environment found)
endif
OBJCOPY_ETC_BANNER := $(shell $(OBJCOPY) --version | grep 'elftoolchain')
ifneq ($(OBJCOPY_ETC_BANNER),)
$(warning The elftoolchain objcopy is unsuitable for building iPXE)
$(warning Use binutils objcopy instead)
$(error Unsuitable build environment found)
endif
###############################################################################
#
# Check if $(eval ...) is available to use
@ -130,74 +94,6 @@ endif
eval :
@$(ECHO) $(HAVE_EVAL)
###############################################################################
#
# Check for various tool workarounds
#
WORKAROUND_CFLAGS :=
WORKAROUND_ASFLAGS :=
WORKAROUND_LDFLAGS :=
# Make syntax does not allow use of comma or space in certain places.
# This ugly workaround is suggested in the manual.
#
COMMA := ,
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
HASH := \#
define NEWLINE
endef
# gcc 4.4 generates .eh_frame sections by default, which distort the
# output of "size". Inhibit this.
#
ifeq ($(CCTYPE),gcc)
CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -fno-exceptions -fno-unwind-tables \
-fno-asynchronous-unwind-tables -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
CFI_FLAGS := $(shell $(CFI_TEST) && \
$(ECHO) '-fno-dwarf2-cfi-asm -fno-exceptions ' \
'-fno-unwind-tables -fno-asynchronous-unwind-tables')
WORKAROUND_CFLAGS += $(CFI_FLAGS)
endif
# gcc 4.6 generates spurious warnings if -Waddress is in force.
# Inhibit this.
#
ifeq ($(CCTYPE),gcc)
WNA_TEST = $(CC) -Waddress -x c -c /dev/null -o /dev/null >/dev/null 2>&1
WNA_FLAGS := $(shell $(WNA_TEST) && $(ECHO) '-Wno-address')
WORKAROUND_CFLAGS += $(WNA_FLAGS)
# gcc 8.0 generates warnings for certain suspect string operations. Our
# sources have been vetted for correct usage. Turn off these warnings.
#
WNST_TEST = $(CC) -Wstringop-truncation -x c -c /dev/null -o /dev/null \
>/dev/null 2>&1
WNST_FLAGS := $(shell $(WNST_TEST) && $(ECHO) '-Wno-stringop-truncation')
WORKAROUND_CFLAGS += $(WNST_FLAGS)
# gcc 9.1 generates warnings for taking address of packed member which
# may result in an unaligned pointer value. Inhibit the warnings.
#
WNAPM_TEST = $(CC) -Wno-address-of-packed-member -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
WNAPM_FLAGS := $(shell $(WNAPM_TEST) && \
$(ECHO) '-Wno-address-of-packed-member')
WORKAROUND_CFLAGS += $(WNAPM_FLAGS)
endif
# Some versions of gas choke on division operators, treating them as
# comment markers. Specifying --divide will work around this problem,
# but isn't available on older gas versions.
#
DIVIDE_TEST = $(AS) --divide /dev/null -o /dev/null 2>/dev/null
DIVIDE_FLAGS := $(shell $(DIVIDE_TEST) && $(ECHO) '--divide')
WORKAROUND_ASFLAGS += $(DIVIDE_FLAGS)
###############################################################################
#
# Build verbosity
@ -284,7 +180,7 @@ ifeq ($(wildcard $(BIN)),)
$(shell $(MKDIR) -p $(BIN))
endif
# Target to allow e.g. "make bin-efi arch"
# Target to allow e.g. "make bin-x86_64-efi arch"
#
$(BIN) :
@# Do nothing, silently
@ -333,8 +229,13 @@ else
BIN_AP := $(BIN_APS)
BIN_SECUREBOOT := 0
endif
BIN_PLATFORM := $(lastword $(BIN_AP))
BIN_ARCH := $(wordlist 2,$(words $(BIN_AP)),discard $(BIN_AP))
ifeq ($(BIN_AP),efi)
BIN_ARCH := i386
BIN_PLATFORM := efi
else
BIN_ARCH := $(word 1,$(BIN_AP))
BIN_PLATFORM := $(word 2,$(BIN_AP))
endif
# Determine build architecture
DEFAULT_ARCH := i386
@ -345,8 +246,12 @@ arch :
.PHONY : arch
# Determine build platform
DEFAULT_PLATFORM := pcbios
PLATFORM := $(firstword $(BIN_PLATFORM) $(DEFAULT_PLATFORM))
DEFAULT_PLATFORM_i386 := pcbios
DEFAULT_PLATFORM_x86_64 := pcbios
DEFAULT_PLATFORM_riscv32 := sbi
DEFAULT_PLATFORM_riscv64 := sbi
DEFAULT_PLATFORM := $(DEFAULT_PLATFORM_$(ARCH))
PLATFORM := $(firstword $(BIN_PLATFORM) $(DEFAULT_PLATFORM) none)
CFLAGS += -DPLATFORM=$(PLATFORM) -DPLATFORM_$(PLATFORM)
platform :
@$(ECHO) $(PLATFORM)
@ -358,9 +263,124 @@ CFLAGS += -DSECUREBOOT=$(SECUREBOOT)
secureboot :
@$(ECHO) $(SECUREBOOT)
# Set cross-compilation prefix automatically if not specified
ifeq ($(CROSS_COMPILE),)
CROSS_COMPILE := $(CROSS_COMPILE_$(ARCH))
endif
endif # defined(BIN)
###############################################################################
#
# Determine compiler
CCDEFS := $(shell $(CC) -E -x c -c /dev/null -dM | cut -d" " -f2)
ccdefs:
@$(ECHO) $(CCDEFS)
ifeq ($(filter __GNUC__,$(CCDEFS)),__GNUC__)
CCTYPE := gcc
endif
cctype:
@$(ECHO) $(CCTYPE)
###############################################################################
#
# Check for tools that can cause failed builds
#
ifeq ($(CCTYPE),gcc)
GCC_2_96_BANNER := $(shell $(CC) -v 2>&1 | grep -is 'gcc version 2\.96')
ifneq ($(GCC_2_96_BANNER),)
$(warning gcc 2.96 is unsuitable for compiling iPXE)
$(warning Use gcc 2.95 or a newer version instead)
$(error Unsuitable build environment found)
endif
endif
PERL_UNICODE_CHECK := $(shell $(PERL) -e 'use bytes; print chr(255)' | wc -c)
ifeq ($(PERL_UNICODE_CHECK),2)
$(warning Your Perl version has a Unicode handling bug)
$(warning Execute this command before building iPXE:)
$(warning export LANG=$${LANG%.UTF-8})
$(error Unsuitable build environment found)
endif
LD_GOLD_BANNER := $(shell $(LD) -v 2>&1 | grep 'GNU gold')
ifneq ($(LD_GOLD_BANNER),)
$(warning GNU gold is unsuitable for building iPXE)
$(warning Use GNU ld instead)
$(error Unsuitable build environment found)
endif
OBJCOPY_ETC_BANNER := $(shell $(OBJCOPY) --version | grep 'elftoolchain')
ifneq ($(OBJCOPY_ETC_BANNER),)
$(warning The elftoolchain objcopy is unsuitable for building iPXE)
$(warning Use binutils objcopy instead)
$(error Unsuitable build environment found)
endif
###############################################################################
#
# Check for various tool workarounds
#
WORKAROUND_CFLAGS :=
WORKAROUND_ASFLAGS :=
WORKAROUND_LDFLAGS :=
# gcc 4.4 generates .eh_frame sections by default, which distort the
# output of "size". Inhibit this.
#
ifeq ($(CCTYPE),gcc)
CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -fno-exceptions -fno-unwind-tables \
-fno-asynchronous-unwind-tables -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
CFI_FLAGS := $(shell $(CFI_TEST) && \
$(ECHO) '-fno-dwarf2-cfi-asm -fno-exceptions ' \
'-fno-unwind-tables -fno-asynchronous-unwind-tables')
WORKAROUND_CFLAGS += $(CFI_FLAGS)
endif
# gcc 4.6 generates spurious warnings if -Waddress is in force.
# Inhibit this.
#
ifeq ($(CCTYPE),gcc)
WNA_TEST = $(CC) -Waddress -x c -c /dev/null -o /dev/null >/dev/null 2>&1
WNA_FLAGS := $(shell $(WNA_TEST) && $(ECHO) '-Wno-address')
WORKAROUND_CFLAGS += $(WNA_FLAGS)
# gcc 8.0 generates warnings for certain suspect string operations. Our
# sources have been vetted for correct usage. Turn off these warnings.
#
WNST_TEST = $(CC) -Wstringop-truncation -x c -c /dev/null -o /dev/null \
>/dev/null 2>&1
WNST_FLAGS := $(shell $(WNST_TEST) && $(ECHO) '-Wno-stringop-truncation')
WORKAROUND_CFLAGS += $(WNST_FLAGS)
# gcc 9.1 generates warnings for taking address of packed member which
# may result in an unaligned pointer value. Inhibit the warnings.
#
WNAPM_TEST = $(CC) -Wno-address-of-packed-member -x c -c /dev/null \
-o /dev/null >/dev/null 2>&1
WNAPM_FLAGS := $(shell $(WNAPM_TEST) && \
$(ECHO) '-Wno-address-of-packed-member')
WORKAROUND_CFLAGS += $(WNAPM_FLAGS)
endif
# Some versions of gas choke on division operators, treating them as
# comment markers. Specifying --divide will work around this problem,
# but isn't available on older gas versions.
#
DIVIDE_TEST = $(AS) --divide /dev/null -o /dev/null 2>/dev/null
DIVIDE_FLAGS := $(shell $(DIVIDE_TEST) && $(ECHO) '--divide')
WORKAROUND_ASFLAGS += $(DIVIDE_FLAGS)
###############################################################################
#
# Include architecture-specific Makefile
#
ifdef ARCH
MAKEDEPS += arch/$(ARCH)/Makefile
include arch/$(ARCH)/Makefile

View File

@ -11,6 +11,7 @@ INCDIRS := arch/$(ARCH)/include arch/riscv/include $(INCDIRS)
#
SRCDIRS += arch/riscv/core
SRCDIRS += arch/riscv/interface/sbi
SRCDIRS += arch/riscv/prefix
# RISCV-specific flags
#

View File

@ -0,0 +1,16 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Build a position-independent executable, with relocations required
# only for data values. Runtime relocations are applied by the
# prefix code.
#
CFLAGS += -mcmodel=medany -fpie
LDFLAGS += -pie --no-dynamic-linker
# Linker script
#
LDSCRIPT = arch/riscv/scripts/sbi.lds
# Media types
#
MEDIA += sbi

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/** @file
*
* Internal stack
*
*/
.section ".note.GNU-stack", "", @progbits
.text
#define STACK_ALIGN 16
#define STACK_SIZE 8192
.section ".stack", "aw", @nobits
.balign STACK_ALIGN
.globl _stack
_stack:
.space STACK_SIZE
.globl _estack
_estack:

View File

@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <errno.h>
#include <ipxe/hart.h>
#include <ipxe/csr.h>
#include <ipxe/entropy.h>
#include <ipxe/drbg.h>
@ -60,6 +61,12 @@ static int zkr_entropy_enable ( void ) {
return rc;
}
/* Check if seed CSR is accessible in S-mode */
if ( ! csr_can_write ( "seed", 0 ) ) {
DBGC ( colour, "ZKR cannot access seed CSR\n" );
return -ENOTSUP;
}
/* RISC-V ISA mandates that 128 bits of full entropy shall be
* obtained from 256 entropy bits read from the seed CSR.
*

View File

@ -0,0 +1,14 @@
#ifndef _BITS_UMALLOC_H
#define _BITS_UMALLOC_H
/** @file
*
* RISCV-specific user memory allocation API implementations
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/sbi_umalloc.h>
#endif /* _BITS_UMALLOC_H */

View File

@ -0,0 +1,75 @@
#ifndef _IPXE_CSR_H
#define _IPXE_CSR_H
/** @file
*
* Control and status registers (CSRs)
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* Check if CSR can be read
*
* @v name CSR name
* @v allowed CSR can be read
*/
#define csr_can_read( name ) ( { \
unsigned long stvec_orig; \
unsigned long stvec_temp; \
unsigned long csr; \
int allowed = 0; \
\
__asm__ __volatile__ ( /* Set temporary trap vector */ \
"la %3, 1f\n\t" \
"csrrw %2, stvec, %3\n\t" \
/* Try reading CSR */ \
"csrr %1, " name "\n\t" \
/* Mark as allowed if not trapped */ \
"addi %0, %0, 1\n\t" \
/* Temporary trap vector */ \
".balign 4\n\t" \
"\n1:\n\t" \
/* Restore original trap vector */ \
"csrw stvec, %2\n\t" \
: "+r" ( allowed ), \
"=r" ( csr ), \
"=r" ( stvec_orig ), \
"=r" ( stvec_temp ) ); \
allowed; \
} )
/**
* Check if CSR can be written
*
* @v name CSR name
* @v value Value to write
* @v allowed CSR can be written
*/
#define csr_can_write( name, value ) ( { \
unsigned long stvec_orig; \
unsigned long stvec_temp; \
unsigned long csr = (value); \
int allowed = 0; \
\
__asm__ __volatile__ ( /* Set temporary trap vector */ \
"la %3, 1f\n\t" \
"csrrw %2, stvec, %3\n\t" \
/* Try writing CSR */ \
"csrrw %1, " name ", %1\n\t" \
/* Mark as allowed if not trapped */ \
"addi %0, %0, 1\n\t" \
/* Temporary trap vector */ \
".balign 4\n\t" \
"\n1:\n\t" \
/* Restore original trap vector */ \
"csrw stvec, %2\n\t" \
: "+r" ( allowed ), \
"+r" ( csr ), \
"=r" ( stvec_orig ), \
"=r" ( stvec_temp ) ); \
allowed; \
} )
#endif /* _IPXE_CSR_H */

View File

@ -0,0 +1,19 @@
#ifndef _IPXE_ERRNO_SBI_H
#define _IPXE_ERRNO_SBI_H
/**
* @file
*
* RISC-V SBI platform error codes
*
* We never need to return SBI error codes ourselves, so we
* arbitrarily choose to use the Linux error codes as platform error
* codes.
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/errno/linux.h>
#endif /* _IPXE_ERRNO_SBI_H */

View File

@ -0,0 +1,18 @@
#ifndef _IPXE_SBI_UMALLOC_H
#define _IPXE_SBI_UMALLOC_H
/** @file
*
* External memory allocation
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef UMALLOC_SBI
#define UMALLOC_PREFIX_sbi
#else
#define UMALLOC_PREFIX_sbi __sbi_
#endif
#endif /* _IPXE_SBI_UMALLOC_H */

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdlib.h>
#include <ipxe/umalloc.h>
/** @file
*
* iPXE user memory allocation API for SBI
*
*/
/** Equivalent of NOWHERE for user pointers */
#define UNOWHERE ( ~UNULL )
/**
* Reallocate external memory
*
* @v old_ptr Memory previously allocated by umalloc(), or UNULL
* @v new_size Requested size
* @ret new_ptr Allocated memory, or UNULL
*
* Calling realloc() with a new size of zero is a valid way to free a
* memory block.
*/
static userptr_t sbi_urealloc ( userptr_t old_ptr, size_t new_size ) {
/* External allocation not yet implemented: allocate from heap */
return ( ( userptr_t ) realloc ( ( ( void * ) old_ptr ), new_size ) );
}
PROVIDE_UMALLOC ( sbi, urealloc, sbi_urealloc );

View File

@ -0,0 +1,156 @@
/*
* Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/** @file
*
* SBI position-independent executable prefix
*
*/
.section ".note.GNU-stack", "", @progbits
.text
/* SBI debug console extension */
#define SBI_DBCN ( ( 'D' << 24 ) | ( 'B' << 16 ) | ( 'C' << 8 ) | 'N' )
#define SBI_DBCN_WRITE 0x00
/* SBI system reset extension */
#define SBI_SRST ( ( 'S' << 24 ) | ( 'R' << 16 ) | ( 'S' << 8 ) | 'T' )
#define SBI_SRST_SYSTEM_RESET 0x00
#define SBI_RESET_COLD 0x00000001
/* Relative relocation type */
#define R_RISCV_RELATIVE 3
/* Layout of a relocation record */
.struct 0
rela_offset: .space ( __riscv_xlen / 8 )
rela_type: .space ( __riscv_xlen / 8 )
rela_addend: .space ( __riscv_xlen / 8 )
rela_len:
.previous
/*
* Display progress message via debug console
*/
.macro progress message
#ifndef NDEBUG
.section ".prefix.data", "aw", @progbits
progress_\@:
.ascii "\message"
.equ progress_\@_len, . - progress_\@
.size progress_\@, . - progress_\@
.previous
li a7, SBI_DBCN
li a6, SBI_DBCN_WRITE
li a0, progress_\@_len
la a1, progress_\@
mv a2, zero
ecall
#endif
.endm
/*
* SBI entry point
*/
.section ".prefix", "ax", @progbits
.org 0
.globl _sbi_start
_sbi_start:
/* Preserve arguments */
mv s0, a0
mv s1, a1
progress "\nSBI->iPXE"
/* Apply dynamic relocations */
la t0, _reloc
la t1, _ereloc
la t2, _sbi_start
1: /* Read relocation record */
LOADN t3, rela_offset(t0)
LOADN t4, rela_type(t0)
LOADN t5, rela_addend(t0)
/* Check relocation type */
addi t4, t4, -R_RISCV_RELATIVE
bnez t4, 2f
/* Apply relocation */
add t3, t3, t2
add t5, t5, t2
STOREN t5, (t3)
2: /* Loop */
addi t0, t0, rela_len
blt t0, t1, 1b
progress " .reloc"
/* Zero the bss */
la t0, _bss
la t1, _ebss
1: STOREN zero, (t0)
addi t0, t0, ( __riscv_xlen / 8 )
blt t0, t1, 1b
progress " .bss"
/* Set up stack */
la sp, _estack
progress " .stack"
/* Store boot hart */
la t0, boot_hart
STOREN s0, (t0)
/* Register device tree */
mv a0, s1
call register_fdt
/* Call main program */
progress "\n\n"
call main
/* We have no return path, since the M-mode SBI implementation
* will have jumped to us by setting our start address in MEPC
* and issuing an MRET instruction.
*
* Attempt a system reset, since there is nothing else we can
* viably do at this point.
*/
progress "\niPXE->SBI reset\n"
li a7, SBI_SRST
li a6, SBI_SRST_SYSTEM_RESET
li a0, SBI_RESET_COLD
mv a1, zero
ecall
/* If reset failed, lock the system */
progress "(reset failed)\n"
1: wfi
j 1b
.size _sbi_start, . - _sbi_start
/* File split information for the compressor */
.section ".zinfo", "a", @progbits
.ascii "COPY"
.word 0
.word _sbi_filesz
.word 1

View File

@ -0,0 +1,119 @@
/*
* Linker script for RISC-V SBI images
*
*/
SECTIONS {
/* Start at virtual address zero */
. = 0;
/* Weak symbols that need zero values if not otherwise defined */
.weak 0x0 : {
_weak = .;
*(.weak)
*(.weak.*)
_eweak = .;
}
_assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
/* Prefix code */
.prefix : {
_prefix = .;
*(.prefix)
*(.prefix.*)
_eprefix = .;
}
/* Program code */
.text : {
_text = .;
*(.text)
*(.text.*)
_etext = .;
}
/* Align to page size to allow linker to generate W^X segments */
. = ALIGN ( 4096 );
/* Read-only data */
.rodata : {
_rodata = .;
*(.rodata)
*(.rodata.*)
_erodata = .;
}
/* Writable data */
.data : {
_data = .;
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*))) /* Various tables. See include/tables.h */
KEEP(*(.provided))
KEEP(*(.provided.*))
_edata = .;
}
/* Uninitialised and discardable data */
OVERLAY : {
/* Runtime relocations (discarded after use) */
.rela.dyn {
_reloc = .;
*(.rela)
*(.rela.dyn)
}
/* Compressor information block */
.zinfo {
_zinfo = .;
KEEP(*(.zinfo))
KEEP(*(.zinfo.*))
_ezinfo = .;
}
/* Uninitialised data */
.bss {
_bss = .;
*(.bss)
*(.bss.*)
*(COMMON)
*(.stack)
*(.stack.*)
/* Align to allow for easy zeroing by prefix code */
. = ALIGN ( 16 );
_ebss = .;
}
}
/* Calculate end of relocations
*
* This cannot be done by placing "_ereloc = .;" inside the
* .rela.dyn section, since the dynamic relocations are not
* present in the input sections but are instead generated during
* linking.
*/
_ereloc = ( _reloc + __load_stop_reladyn - __load_start_reladyn );
/* Length of initialised data */
_sbi_filesz = ABSOLUTE ( _ereloc );
/* Unwanted sections */
/DISCARD/ : {
*(.comment)
*(.comment.*)
*(.note)
*(.note.*)
*(.eh_frame)
*(.eh_frame.*)
*(.dynamic)
*(.dynsym)
*(.dynstr)
*(.einfo)
*(.einfo.*)
*(.discard)
*(.discard.*)
*(.pci_devlist.*)
}
}

View File

@ -0,0 +1,6 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Include generic SBI Makefile
#
MAKEDEPS += arch/riscv/Makefile.sbi
include arch/riscv/Makefile.sbi

View File

@ -0,0 +1,20 @@
#ifndef _IPXE_SBI_DHCPARCH_H
#define _IPXE_SBI_DHCPARCH_H
/** @file
*
* DHCP client architecture definitions
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
/** DHCP client architecture */
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_RISCV32
/** DHCP client network device interface */
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
#endif /* _IPXE_SBI_DHCPARCH_H */

View File

@ -0,0 +1,6 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Include generic SBI Makefile
#
MAKEDEPS += arch/riscv/Makefile.sbi
include arch/riscv/Makefile.sbi

View File

@ -0,0 +1,20 @@
#ifndef _IPXE_SBI_DHCPARCH_H
#define _IPXE_SBI_DHCPARCH_H
/** @file
*
* DHCP client architecture definitions
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
/** DHCP client architecture */
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_RISCV64
/** DHCP client network device interface */
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
#endif /* _IPXE_SBI_DHCPARCH_H */

0
src/config/config_sbi.c Normal file
View File

36
src/config/defaults/sbi.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef CONFIG_DEFAULTS_SBI_H
#define CONFIG_DEFAULTS_SBI_H
/** @file
*
* Configuration defaults for RISC-V SBI
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IOAPI_RISCV
#define IOMAP_VIRT
#define DMAAPI_FLAT
#define UACCESS_FLAT
#define TIMER_ZICNTR
#define ENTROPY_ZKR
#define CONSOLE_SBI
#define REBOOT_SBI
#define UMALLOC_SBI
#define ACPI_NULL
#define MPAPI_NULL
#define NAP_NULL
#define PCIAPI_NULL
#define SANBOOT_NULL
#define SMBIOS_NULL
#define TIME_NULL
#define IMAGE_SCRIPT
#define REBOOT_CMD
#define POWEROFF_CMD
#endif /* CONFIG_DEFAULTS_SBI_H */