[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>
This commit is contained in:
Michael Brown 2024-10-28 14:40:35 +00:00
parent 7ccd08dbf4
commit e0e102ee24
16 changed files with 532 additions and 0 deletions

View File

@ -352,6 +352,8 @@ arch :
# Determine build 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)

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

@ -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,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 */