- Support SPL and OpenSBI (FW_DYNAMIC firmware) boot.
- Fix qemu kconfig build warning.
This commit is contained in:
Tom Rini 2019-08-26 09:50:46 -04:00
commit 7a4b0bc5fe
32 changed files with 692 additions and 42 deletions

View file

@ -252,7 +252,8 @@ config BUILD_TARGET
default "u-boot-with-spl.sfp" if TARGET_SOCFPGA_GEN5
default "u-boot-spl.kwb" if ARCH_MVEBU && SPL
default "u-boot-elf.srec" if RCAR_GEN3
default "u-boot.itb" if SPL_LOAD_FIT && (ROCKCHIP_RK3399 || ARCH_SUNXI)
default "u-boot.itb" if SPL_LOAD_FIT && (ROCKCHIP_RK3399 || \
ARCH_SUNXI || RISCV)
default "u-boot.kwb" if KIRKWOOD
default "u-boot-with-spl.bin" if ARCH_AT91 && SPL_NAND_SUPPORT
help
@ -465,6 +466,7 @@ config SPL_FIT_GENERATOR
depends on SPL_FIT
default "board/sunxi/mksunxi_fit_atf.sh" if SPL_LOAD_FIT && ARCH_SUNXI
default "arch/arm/mach-rockchip/make_fit_atf.py" if SPL_LOAD_FIT && ARCH_ROCKCHIP
default "arch/riscv/lib/mkimage_fit_opensbi.sh" if SPL_LOAD_FIT && RISCV
help
Specifies a (platform specific) script file to generate the FIT
source file used to build the U-Boot FIT image file. This gets

View file

@ -1257,7 +1257,9 @@ MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
-R $(srctree)/$(CONFIG_SYS_FSL_PBL_PBI:"%"=%) -T pblimage
u-boot-dtb.img u-boot.img u-boot.kwb u-boot.pbl u-boot-ivt.img: \
$(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin dts/dt.dtb,u-boot.bin) FORCE
$(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin \
$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_OF_HOSTFILE),dts/dt.dtb) \
,u-boot.bin) FORCE
$(call if_changed,mkimage)
$(BOARD_SIZE_CHECK)
@ -1267,7 +1269,9 @@ else
MKIMAGEFLAGS_u-boot.itb = -E
endif
u-boot.itb: u-boot-nodtb.bin dts/dt.dtb $(U_BOOT_ITS) FORCE
u-boot.itb: u-boot-nodtb.bin \
$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_OF_HOSTFILE),dts/dt.dtb) \
$(U_BOOT_ITS) FORCE
$(call if_changed,mkfitimage)
$(BOARD_SIZE_CHECK)

View file

@ -76,6 +76,12 @@ config RISCV
imply MTD
imply TIMER
imply CMD_DM
imply SPL_DM
imply SPL_OF_CONTROL
imply SPL_LIBCOMMON_SUPPORT
imply SPL_LIBGENERIC_SUPPORT
imply SPL_SERIAL_SUPPORT
imply SPL_TIMER
config SANDBOX
bool "Sandbox"

View file

@ -113,6 +113,23 @@ config RISCV_SMODE
endchoice
choice
prompt "SPL Run Mode"
default SPL_RISCV_MMODE
depends on SPL
config SPL_RISCV_MMODE
bool "Machine"
help
Choose this option to build U-Boot SPL for RISC-V M-Mode.
config SPL_RISCV_SMODE
bool "Supervisor"
help
Choose this option to build U-Boot SPL for RISC-V S-Mode.
endchoice
config RISCV_ISA_C
bool "Emit compressed instructions"
default y
@ -132,34 +149,40 @@ config 64BIT
config SIFIVE_CLINT
bool
depends on RISCV_MMODE
depends on RISCV_MMODE || SPL_RISCV_MMODE
select REGMAP
select SYSCON
select SPL_REGMAP if SPL
select SPL_SYSCON if SPL
help
The SiFive CLINT block holds memory-mapped control and status registers
associated with software and timer interrupts.
config ANDES_PLIC
bool
depends on RISCV_MMODE
depends on RISCV_MMODE || SPL_RISCV_MMODE
select REGMAP
select SYSCON
select SPL_REGMAP if SPL
select SPL_SYSCON if SPL
help
The Andes PLIC block holds memory-mapped claim and pending registers
associated with software interrupt.
config ANDES_PLMT
bool
depends on RISCV_MMODE
depends on RISCV_MMODE || SPL_RISCV_MMODE
select REGMAP
select SYSCON
select SPL_REGMAP if SPL
select SPL_SYSCON if SPL
help
The Andes PLMT block holds memory-mapped mtime register
associated with timer tick.
config RISCV_RDTIME
bool
default y if RISCV_SMODE
default y if RISCV_SMODE || SPL_RISCV_SMODE
help
The provides the riscv_get_time() API that is implemented using the
standard rdtime instruction. This is the case for S-mode U-Boot, and
@ -189,7 +212,7 @@ config NR_CPUS
config SBI_IPI
bool
default y if RISCV_SMODE
default y if RISCV_SMODE || SPL_RISCV_SMODE
depends on SMP
config XIP
@ -203,4 +226,7 @@ config STACK_SIZE_SHIFT
int
default 13
config SPL_LDSCRIPT
default "arch/riscv/cpu/u-boot-spl.lds"
endmenu

View file

@ -4,8 +4,8 @@ config RISCV_NDS
imply CPU
imply CPU_RISCV
imply RISCV_TIMER
imply ANDES_PLIC if RISCV_MMODE
imply ANDES_PLMT if RISCV_MMODE
imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE)
imply ANDES_PLMT if (RISCV_MMODE || SPL_RISCV_MMODE)
help
Run U-Boot on AndeStar V5 platforms and use some specific features
which are provided by Andes Technology AndeStar V5 families.
@ -14,7 +14,7 @@ if RISCV_NDS
config RISCV_NDS_CACHE
bool "AndeStar V5 families specific cache support"
depends on RISCV_MMODE
depends on RISCV_MMODE || SPL_RISCV_MMODE
help
Provide Andes Technology AndeStar V5 families specific cache support.

View file

@ -46,13 +46,13 @@ static inline bool supports_extension(char ext)
return false;
#else /* !CONFIG_CPU */
#ifdef CONFIG_RISCV_MMODE
#if CONFIG_IS_ENABLED(RISCV_MMODE)
return csr_read(CSR_MISA) & (1 << (ext - 'a'));
#else /* !CONFIG_RISCV_MMODE */
#else /* !CONFIG_IS_ENABLED(RISCV_MMODE) */
#warning "There is no way to determine the available extensions in S-mode."
#warning "Please convert your board to use the RISC-V CPU driver."
return false;
#endif /* CONFIG_RISCV_MMODE */
#endif /* CONFIG_IS_ENABLED(RISCV_MMODE) */
#endif /* CONFIG_CPU */
}

View file

@ -8,5 +8,8 @@ config GENERIC_RISCV
imply CPU
imply CPU_RISCV
imply RISCV_TIMER
imply SIFIVE_CLINT if RISCV_MMODE
imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE)
imply CMD_CPU
imply SPL_CPU_SUPPORT
imply SPL_OPENSBI
imply SPL_LOAD_FIT

View file

@ -39,7 +39,7 @@ secondary_harts_relocation_error:
.section .text
.globl _start
_start:
#ifdef CONFIG_RISCV_MMODE
#if CONFIG_IS_ENABLED(RISCV_MMODE)
csrr a0, CSR_MHARTID
#endif
@ -62,7 +62,7 @@ _start:
#ifdef CONFIG_SMP
/* set xSIE bit to receive IPIs */
#ifdef CONFIG_RISCV_MMODE
#if CONFIG_IS_ENABLED(RISCV_MMODE)
li t0, MIE_MSIE
#else
li t0, SIE_SSIE
@ -75,7 +75,11 @@ _start:
*/
call_board_init_f:
li t0, -16
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
li t1, CONFIG_SPL_STACK
#else
li t1, CONFIG_SYS_INIT_SP_ADDR
#endif
and sp, t1, t0 /* force 16 byte alignment */
call_board_init_f_0:
@ -159,7 +163,57 @@ wait_for_gd_init:
mv a0, zero /* a0 <-- boot_flags = 0 */
la t5, board_init_f
jr t5 /* jump to board_init_f() */
jalr t5 /* jump to board_init_f() */
#ifdef CONFIG_SPL_BUILD
spl_clear_bss:
la t0, __bss_start
la t1, __bss_end
beq t0, t1, spl_stack_gd_setup
spl_clear_bss_loop:
SREG zero, 0(t0)
addi t0, t0, REGBYTES
bne t0, t1, spl_clear_bss_loop
spl_stack_gd_setup:
jal spl_relocate_stack_gd
/* skip setup if we did not relocate */
beqz a0, spl_call_board_init_r
mv s0, a0
/* setup stack on main hart */
#ifdef CONFIG_SMP
/* tp: hart id */
slli t0, tp, CONFIG_STACK_SIZE_SHIFT
sub sp, s0, t0
#else
mv sp, s0
#endif
/* set new stack and global data pointer on secondary harts */
spl_secondary_hart_stack_gd_setup:
la a0, secondary_hart_relocate
mv a1, s0
mv a2, s0
jal smp_call_function
/* hang if relocation of secondary harts has failed */
beqz a0, 1f
mv a1, a0
la a0, secondary_harts_relocation_error
jal printf
jal hang
/* set new global data pointer on main hart */
1: mv gp, s0
spl_call_board_init_r:
mv a0, zero
mv a1, zero
jal board_init_r
#endif
/*
* void relocate_code (addr_sp, gd, addr_moni)
@ -344,7 +398,7 @@ secondary_hart_loop:
#ifdef CONFIG_SMP
csrr t0, MODE_PREFIX(ip)
#ifdef CONFIG_RISCV_MMODE
#if CONFIG_IS_ENABLED(RISCV_MMODE)
andi t0, t0, MIE_MSIE
#else
andi t0, t0, SIE_SSIE

View file

@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Based on arch/riscv/cpu/u-boot.lds, which is
* Copyright (C) 2017 Andes Technology Corporation
* Rick Chen, Andes Technology Corporation <rick@andestech.com>
*
* and arch/mips/cpu/u-boot-spl.lds.
*/
MEMORY { .spl_mem : ORIGIN = IMAGE_TEXT_BASE, LENGTH = IMAGE_MAX_SIZE }
MEMORY { .bss_mem : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
OUTPUT_ARCH("riscv")
ENTRY(_start)
SECTIONS
{
. = ALIGN(4);
.text : {
arch/riscv/cpu/start.o (.text)
*(.text*)
} > .spl_mem
. = ALIGN(4);
.rodata : {
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
} > .spl_mem
. = ALIGN(4);
.data : {
*(.data*)
} > .spl_mem
. = ALIGN(4);
.got : {
__got_start = .;
*(.got.plt) *(.got)
__got_end = .;
} > .spl_mem
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
} > .spl_mem
. = ALIGN(4);
.binman_sym_table : {
__binman_sym_start = .;
KEEP(*(SORT(.binman_sym*)));
__binman_sym_end = .;
} > .spl_mem
. = ALIGN(4);
/DISCARD/ : { *(.rela.plt*) }
.rela.dyn : {
__rel_dyn_start = .;
*(.rela*)
__rel_dyn_end = .;
} > .spl_mem
. = ALIGN(4);
.dynsym : {
__dyn_sym_start = .;
*(.dynsym)
__dyn_sym_end = .;
} > .spl_mem
. = ALIGN(4);
_end = .;
.bss : {
__bss_start = .;
*(.bss*)
. = ALIGN(4);
__bss_end = .;
} > .bss_mem
}

View file

@ -9,7 +9,7 @@
#include <asm/csr.h>
#ifdef CONFIG_RISCV_SMODE
#if CONFIG_IS_ENABLED(RISCV_SMODE)
#define MODE_PREFIX(__suffix) s##__suffix
#else
#define MODE_PREFIX(__suffix) m##__suffix

View file

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Based on arch/mips/include/asm/spl.h.
*
* (C) Copyright 2012
* Texas Instruments, <www.ti.com>
*/
#ifndef _ASM_RISCV_SPL_H_
#define _ASM_RISCV_SPL_H_
enum {
BOOT_DEVICE_RAM,
BOOT_DEVICE_MMC1,
BOOT_DEVICE_MMC2,
BOOT_DEVICE_MMC2_2,
BOOT_DEVICE_NAND,
BOOT_DEVICE_ONENAND,
BOOT_DEVICE_NOR,
BOOT_DEVICE_UART,
BOOT_DEVICE_SPI,
BOOT_DEVICE_USB,
BOOT_DEVICE_SATA,
BOOT_DEVICE_I2C,
BOOT_DEVICE_BOARD,
BOOT_DEVICE_DFU,
BOOT_DEVICE_XIP,
BOOT_DEVICE_BOOTROM,
BOOT_DEVICE_NONE
};
#endif

View file

@ -10,15 +10,19 @@ obj-$(CONFIG_CMD_BOOTM) += bootm.o
obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o
obj-$(CONFIG_CMD_GO) += boot.o
obj-y += cache.o
obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
ifeq ($(CONFIG_$(SPL_)RISCV_MMODE),y)
obj-$(CONFIG_SIFIVE_CLINT) += sifive_clint.o
obj-$(CONFIG_ANDES_PLIC) += andes_plic.o
obj-$(CONFIG_ANDES_PLMT) += andes_plmt.o
else
obj-$(CONFIG_RISCV_RDTIME) += rdtime.o
obj-$(CONFIG_SBI_IPI) += sbi_ipi.o
endif
obj-y += interrupts.o
obj-y += reset.o
obj-$(CONFIG_SBI_IPI) += sbi_ipi.o
obj-y += setjmp.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SPL_BUILD) += spl.o
# For building EFI apps
CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI)

View file

@ -0,0 +1,100 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# script to generate FIT image source for RISC-V boards with OpenSBI
# and, optionally, multiple device trees (given on the command line).
#
# usage: $0 [<dt_name> [<dt_name] ...]
[ -z "$OPENSBI" ] && OPENSBI="fw_dynamic.bin"
if [ -z "$UBOOT_LOAD_ADDR" ]; then
UBOOT_LOAD_ADDR="$(grep "^CONFIG_SYS_TEXT_BASE=" .config | awk 'BEGIN{FS="="} {print $2}')"
fi
if [ -z "$OPENSBI_LOAD_ADDR" ]; then
OPENSBI_LOAD_ADDR="$(grep "^CONFIG_SPL_OPENSBI_LOAD_ADDR=" .config | awk 'BEGIN{FS="="} {print $2}')"
fi
if [ ! -f $OPENSBI ]; then
echo "WARNING: OpenSBI binary \"$OPENSBI\" not found, resulting binary is not functional." >&2
OPENSBI=/dev/null
fi
cat << __HEADER_EOF
/dts-v1/;
/ {
description = "Configuration to load OpenSBI before U-Boot";
images {
uboot {
description = "U-Boot";
data = /incbin/("u-boot-nodtb.bin");
type = "standalone";
os = "U-Boot";
arch = "riscv";
compression = "none";
load = <$UBOOT_LOAD_ADDR>;
};
opensbi {
description = "RISC-V OpenSBI";
data = /incbin/("$OPENSBI");
type = "firmware";
os = "opensbi";
arch = "riscv";
compression = "none";
load = <$OPENSBI_LOAD_ADDR>;
entry = <$OPENSBI_LOAD_ADDR>;
};
__HEADER_EOF
cnt=1
for dtname in $*
do
cat << __FDT_IMAGE_EOF
fdt_$cnt {
description = "$(basename $dtname .dtb)";
data = /incbin/("$dtname");
type = "flat_dt";
compression = "none";
};
__FDT_IMAGE_EOF
cnt=$((cnt+1))
done
cat << __CONF_HEADER_EOF
};
configurations {
default = "config_1";
__CONF_HEADER_EOF
if [ $# -eq 0 ]; then
cat << __CONF_SECTION_EOF
config_1 {
description = "U-Boot FIT";
firmware = "opensbi";
loadables = "uboot";
};
__CONF_SECTION_EOF
else
cnt=1
for dtname in $*
do
cat << __CONF_SECTION_EOF
config_$cnt {
description = "$(basename $dtname .dtb)";
firmware = "opensbi";
loadables = "uboot";
fdt = "fdt_$cnt";
};
__CONF_SECTION_EOF
cnt=$((cnt+1))
done
fi
cat << __ITS_EOF
};
};
__ITS_EOF

48
arch/riscv/lib/spl.c Normal file
View file

@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019 Fraunhofer AISEC,
* Lukas Auer <lukas.auer@aisec.fraunhofer.de>
*/
#include <common.h>
#include <spl.h>
#include <asm/smp.h>
DECLARE_GLOBAL_DATA_PTR;
__weak void board_init_f(ulong dummy)
{
int ret;
ret = spl_early_init();
if (ret)
panic("spl_early_init() failed: %d\n", ret);
arch_cpu_init_dm();
preloader_console_init();
}
void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
{
typedef void __noreturn (*image_entry_riscv_t)(ulong hart, void *dtb);
void *fdt_blob;
int ret;
#if CONFIG_IS_ENABLED(LOAD_FIT) || CONFIG_IS_ENABLED(LOAD_FIT_FULL)
fdt_blob = spl_image->fdt_addr;
#else
fdt_blob = (void *)gd->fdt_blob;
#endif
image_entry_riscv_t image_entry =
(image_entry_riscv_t)spl_image->entry_point;
invalidate_icache_all();
debug("image entry point: 0x%lX\n", spl_image->entry_point);
#ifdef CONFIG_SMP
ret = smp_call_function(spl_image->entry_point, (ulong)fdt_blob, 0);
if (ret)
hang();
#endif
image_entry(gd->arch.boot_hart, fdt_blob);
}

View file

@ -13,13 +13,22 @@ config SYS_CONFIG_NAME
default "qemu-riscv"
config SYS_TEXT_BASE
default 0x81200000 if SPL
default 0x80000000 if !RISCV_SMODE
default 0x80200000 if RISCV_SMODE && ARCH_RV64I
default 0x80400000 if RISCV_SMODE && ARCH_RV32I
config SPL_TEXT_BASE
default 0x80000000
config SPL_OPENSBI_LOAD_ADDR
hex
default 0x81000000
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select GENERIC_RISCV
select SUPPORT_SPL
imply SYS_NS16550
imply VIRTIO_MMIO
imply VIRTIO_NET
@ -43,5 +52,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
imply CMD_PCI
imply E1000
imply NVME
imply SPL_RAM_SUPPORT
imply SPL_RAM_DEVICE
endif

View file

@ -5,5 +5,7 @@ F: board/emulation/qemu-riscv/
F: include/configs/qemu-riscv.h
F: configs/qemu-riscv32_defconfig
F: configs/qemu-riscv32_smode_defconfig
F: configs/qemu-riscv32_spl_defconfig
F: configs/qemu-riscv64_defconfig
F: configs/qemu-riscv64_smode_defconfig
F: configs/qemu-riscv64_spl_defconfig

View file

@ -7,6 +7,7 @@
#include <dm.h>
#include <env.h>
#include <fdtdec.h>
#include <spl.h>
#include <virtio_types.h>
#include <virtio.h>
@ -88,3 +89,19 @@ int ft_board_setup(void *blob, bd_t *bd)
return 0;
}
#ifdef CONFIG_SPL
u32 spl_boot_device(void)
{
/* RISC-V QEMU only supports RAM as SPL boot device */
return BOOT_DEVICE_RAM;
}
#endif
#ifdef CONFIG_SPL_LOAD_FIT
int board_fit_config_name_match(const char *name)
{
/* boot using first FIT config */
return 0;
}
#endif

View file

@ -132,6 +132,7 @@ static const table_entry_t uimage_os[] = {
#if defined(CONFIG_BOOTM_OPENRTOS) || defined(USE_HOSTCC)
{ IH_OS_OPENRTOS, "openrtos", "OpenRTOS", },
#endif
{ IH_OS_OPENSBI, "opensbi", "RISC-V OpenSBI", },
{ -1, "", "", },
};

View file

@ -1156,6 +1156,23 @@ config SPL_OPTEE
OP-TEE is an open source Trusted OS which is loaded by SPL.
More detail at: https://github.com/OP-TEE/optee_os
config SPL_OPENSBI
bool "Support RISC-V OpenSBI"
depends on RISCV && SPL_RISCV_MMODE && RISCV_SMODE
help
OpenSBI is an open-source implementation of the RISC-V Supervisor Binary
Interface (SBI) specification. U-Boot supports the OpenSBI FW_DYNAMIC
firmware. It is loaded and started by U-Boot SPL.
More details are available at https://github.com/riscv/opensbi and
https://github.com/riscv/riscv-sbi-doc
config SPL_OPENSBI_LOAD_ADDR
hex "OpenSBI load address"
depends on SPL_OPENSBI
help
Load address of the OpenSBI binary.
config TPL
bool
depends on SUPPORT_TPL

View file

@ -22,6 +22,7 @@ obj-$(CONFIG_$(SPL_TPL_)NET_SUPPORT) += spl_net.o
obj-$(CONFIG_$(SPL_TPL_)MMC_SUPPORT) += spl_mmc.o
obj-$(CONFIG_$(SPL_TPL_)ATF) += spl_atf.o
obj-$(CONFIG_$(SPL_TPL_)OPTEE) += spl_optee.o
obj-$(CONFIG_$(SPL_TPL_)OPENSBI) += spl_opensbi.o
obj-$(CONFIG_$(SPL_TPL_)USB_STORAGE) += spl_usb.o
obj-$(CONFIG_$(SPL_TPL_)FS_FAT) += spl_fat.o
obj-$(CONFIG_$(SPL_TPL_)FS_EXT4) += spl_ext.o

View file

@ -659,6 +659,12 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
(void *)spl_image.entry_point);
break;
#endif
#if CONFIG_IS_ENABLED(OPENSBI)
case IH_OS_OPENSBI:
debug("Jumping to U-Boot via RISC-V OpenSBI\n");
spl_invoke_opensbi(&spl_image);
break;
#endif
#ifdef CONFIG_SPL_OS_BOOT
case IH_OS_LINUX:
debug("Jumping to Linux\n");
@ -775,7 +781,7 @@ ulong spl_relocate_stack_gd(void)
#if CONFIG_IS_ENABLED(DM)
dm_fixup_for_gd_move(new_gd);
#endif
#if !defined(CONFIG_ARM)
#if !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
gd = new_gd;
#endif
return ptr;

View file

@ -12,6 +12,8 @@
#include <linux/libfdt.h>
#include <spl.h>
DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_SYS_BOOTM_LEN
#define CONFIG_SYS_BOOTM_LEN (64 << 20)
#endif
@ -279,26 +281,35 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image,
void *fit, int images, ulong base_offset)
{
struct spl_image_info image_info;
int node, ret;
int node, ret = 0;
/*
* Use the address following the image as target address for the
* device tree.
*/
image_info.load_addr = spl_image->load_addr + spl_image->size;
/* Figure out which device tree the board wants to use */
node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
if (node < 0) {
debug("%s: cannot find FDT node\n", __func__);
return node;
/*
* U-Boot did not find a device tree inside the FIT image. Use
* the U-Boot device tree instead.
*/
if (gd->fdt_blob)
memcpy((void *)image_info.load_addr, gd->fdt_blob,
fdt_totalsize(gd->fdt_blob));
else
return node;
} else {
ret = spl_load_fit_image(info, sector, fit, base_offset, node,
&image_info);
if (ret < 0)
return ret;
}
/*
* Read the device tree and place it after the image.
* Align the destination address to ARCH_DMA_MINALIGN.
*/
image_info.load_addr = spl_image->load_addr + spl_image->size;
ret = spl_load_fit_image(info, sector, fit, base_offset, node,
&image_info);
if (ret < 0)
return ret;
/* Make the load-address of the FDT available for the SPL framework */
spl_image->fdt_addr = (void *)image_info.load_addr;
#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)

85
common/spl/spl_opensbi.c Normal file
View file

@ -0,0 +1,85 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2019 Fraunhofer AISEC,
* Lukas Auer <lukas.auer@aisec.fraunhofer.de>
*
* Based on common/spl/spl_atf.c
*/
#include <common.h>
#include <errno.h>
#include <spl.h>
#include <asm/smp.h>
#include <opensbi.h>
DECLARE_GLOBAL_DATA_PTR;
struct fw_dynamic_info opensbi_info;
static int spl_opensbi_find_uboot_node(void *blob, int *uboot_node)
{
int fit_images_node, node;
const char *fit_os;
fit_images_node = fdt_path_offset(blob, "/fit-images");
if (fit_images_node < 0)
return -ENODEV;
fdt_for_each_subnode(node, blob, fit_images_node) {
fit_os = fdt_getprop(blob, node, FIT_OS_PROP, NULL);
if (!fit_os)
continue;
if (genimg_get_os_id(fit_os) == IH_OS_U_BOOT) {
*uboot_node = node;
return 0;
}
}
return -ENODEV;
}
void spl_invoke_opensbi(struct spl_image_info *spl_image)
{
int ret, uboot_node;
ulong uboot_entry;
void (*opensbi_entry)(ulong hartid, ulong dtb, ulong info);
if (!spl_image->fdt_addr) {
pr_err("No device tree specified in SPL image\n");
hang();
}
/* Find U-Boot image in /fit-images */
ret = spl_opensbi_find_uboot_node(spl_image->fdt_addr, &uboot_node);
if (ret) {
pr_err("Can't find U-Boot node, %d", ret);
hang();
}
/* Get U-Boot entry point */
uboot_entry = fdt_getprop_u32(spl_image->fdt_addr, uboot_node,
"entry-point");
if (uboot_entry == FDT_ERROR)
uboot_entry = fdt_getprop_u32(spl_image->fdt_addr, uboot_node,
"load-addr");
/* Prepare obensbi_info object */
opensbi_info.magic = FW_DYNAMIC_INFO_MAGIC_VALUE;
opensbi_info.version = FW_DYNAMIC_INFO_VERSION;
opensbi_info.next_addr = uboot_entry;
opensbi_info.next_mode = FW_DYNAMIC_INFO_NEXT_MODE_S;
opensbi_info.options = SBI_SCRATCH_NO_BOOT_PRINTS;
opensbi_entry = (void (*)(ulong, ulong, ulong))spl_image->entry_point;
invalidate_icache_all();
#ifdef CONFIG_SMP
ret = smp_call_function((ulong)spl_image->entry_point,
(ulong)spl_image->fdt_addr,
(ulong)&opensbi_info);
if (ret)
hang();
#endif
opensbi_entry(gd->arch.boot_hart, (ulong)spl_image->fdt_addr,
(ulong)&opensbi_info);
}

View file

@ -0,0 +1,11 @@
CONFIG_RISCV=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_SPL=y
CONFIG_TARGET_QEMU_VIRT=y
CONFIG_RISCV_SMODE=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_FIT=y
CONFIG_DISPLAY_CPUINFO=y
CONFIG_DISPLAY_BOARDINFO=y
# CONFIG_CMD_MII is not set
CONFIG_OF_PRIOR_STAGE=y

View file

@ -0,0 +1,12 @@
CONFIG_RISCV=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_SPL=y
CONFIG_TARGET_QEMU_VIRT=y
CONFIG_ARCH_RV64I=y
CONFIG_RISCV_SMODE=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_FIT=y
CONFIG_DISPLAY_CPUINFO=y
CONFIG_DISPLAY_BOARDINFO=y
# CONFIG_CMD_MII is not set
CONFIG_OF_PRIOR_STAGE=y

View file

@ -6,7 +6,8 @@ QEMU RISC-V
QEMU for RISC-V supports a special 'virt' machine designed for emulation and
virtualization purposes. This document describes how to run U-Boot under it.
Both 32-bit 64-bit targets are supported.
Both 32-bit and 64-bit targets are supported, running in either machine or
supervisor mode.
The QEMU virt machine models a generic RISC-V virtual machine with support for
the VirtIO standard networking and block storage devices. It has CLINT, PLIC,
@ -28,6 +29,11 @@ Set the CROSS_COMPILE environment variable as usual, and run:
make qemu-riscv64_defconfig
make
This will compile U-Boot for machine mode. To build supervisor mode binaries,
use the configurations qemu-riscv32_smode_defconfig and
qemu-riscv64_smode_defconfig instead. Note that U-Boot running in supervisor
mode requires a supervisor binary interface (SBI), such as RISC-V OpenSBI.
Running U-Boot
--------------
The minimal QEMU command line to get U-Boot up and running is:
@ -46,4 +52,56 @@ parameter. For example, '-m 2G' creates 2GiB memory for the target,
and the memory node in the embedded DTB created by QEMU reflects
the new setting.
For instructions on how to run U-Boot in supervisor mode on QEMU
with OpenSBI, see the documentation available with OpenSBI:
https://github.com/riscv/opensbi/blob/master/docs/platform/qemu_virt.md
These have been tested in QEMU 3.0.0.
Running U-Boot SPL
------------------
In the default SPL configuration, U-Boot SPL starts in machine mode. U-Boot
proper and OpenSBI (FW_DYNAMIC firmware) are bundled as FIT image and made
available to U-Boot SPL. Both are then loaded by U-Boot SPL and the location
of U-Boot proper is passed to OpenSBI. After initialization, U-Boot proper is
started in supervisor mode by OpenSBI.
OpenSBI must be compiled before compiling U-Boot. Version 0.4 and higher is
supported by U-Boot. Clone the OpenSBI repository and run the following command.
.. code-block:: console
git clone https://github.com/riscv/opensbi.git
cd opensbi
make PLATFORM=qemu/virt
See the OpenSBI documentation for full details:
https://github.com/riscv/opensbi/blob/master/docs/platform/qemu_virt.md
To make the FW_DYNAMIC binary (build/platform/qemu/virt/firmware/fw_dynamic.bin)
available to U-Boot, either copy it into the U-Boot root directory or specify
its location with the OPENSBI environment variable. Afterwards, compile U-Boot
with the following commands.
- For 32-bit RISC-V::
make qemu-riscv32_spl_defconfig
make
- For 64-bit RISC-V::
make qemu-riscv64_spl_defconfig
make
The minimal QEMU commands to run U-Boot SPL in both 32-bit and 64-bit
configurations are:
- For 32-bit RISC-V::
qemu-system-riscv32 -nographic -machine virt -kernel spl/u-boot-spl \
-device loader,file=u-boot.itb,addr=0x80200000
- For 64-bit RISC-V::
qemu-system-riscv64 -nographic -machine virt -kernel spl/u-boot-spl \
-device loader,file=u-boot.itb,addr=0x80200000

View file

@ -8,6 +8,18 @@
#include <linux/sizes.h>
#ifdef CONFIG_SPL
#define CONFIG_SPL_MAX_SIZE 0x00100000
#define CONFIG_SPL_BSS_START_ADDR 0x84000000
#define CONFIG_SPL_BSS_MAX_SIZE 0x00100000
#define CONFIG_SYS_SPL_MALLOC_START 0x84100000
#define CONFIG_SYS_SPL_MALLOC_SIZE 0x00100000
#define CONFIG_SPL_LOAD_FIT_ADDRESS 0x80200000
#endif
#define CONFIG_SYS_SDRAM_BASE 0x80000000
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + SZ_2M)
@ -22,6 +34,7 @@
/* Environment options */
#define CONFIG_ENV_SIZE SZ_128K
#ifndef CONFIG_SPL_BUILD
#define BOOT_TARGET_DEVICES(func) \
func(QEMU, qemu, na) \
func(VIRTIO, virtio, 0) \
@ -47,5 +60,6 @@
"pxefile_addr_r=0x88200000\0" \
"ramdisk_addr_r=0x88300000\0" \
BOOTENV
#endif
#endif /* __CONFIG_H */

View file

@ -54,7 +54,7 @@ struct bd_info;
#define SPL_BUILD 0
#endif
#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
#ifdef CONFIG_OF_PRIOR_STAGE
extern phys_addr_t prior_stage_fdt_address;
#endif

View file

@ -156,6 +156,7 @@ enum {
IH_OS_OPENRTOS, /* OpenRTOS */
IH_OS_ARM_TRUSTED_FIRMWARE, /* ARM Trusted Firmware */
IH_OS_TEE, /* Trusted Execution Environment */
IH_OS_OPENSBI, /* RISC-V OpenSBI */
IH_OS_COUNT,
};

40
include/opensbi.h Normal file
View file

@ -0,0 +1,40 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
*
* Based on include/sbi/{fw_dynamic.h,sbi_scratch.h} from the OpenSBI project.
*/
#ifndef OPENSBI_H
#define OPENSBI_H
/** Expected value of info magic ('OSBI' ascii string in hex) */
#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f
/** Maximum supported info version */
#define FW_DYNAMIC_INFO_VERSION 0x1
/** Possible next mode values */
#define FW_DYNAMIC_INFO_NEXT_MODE_U 0x0
#define FW_DYNAMIC_INFO_NEXT_MODE_S 0x1
#define FW_DYNAMIC_INFO_NEXT_MODE_M 0x3
enum sbi_scratch_options {
/** Disable prints during boot */
SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0),
};
/** Representation dynamic info passed by previous booting stage */
struct fw_dynamic_info {
/** Info magic */
unsigned long magic;
/** Info version */
unsigned long version;
/** Next booting stage address */
unsigned long next_addr;
/** Next booting stage mode */
unsigned long next_mode;
/** Options for OpenSBI library */
unsigned long options;
} __packed;
#endif

View file

@ -374,6 +374,11 @@ void spl_invoke_atf(struct spl_image_info *spl_image);
*/
void spl_optee_entry(void *arg0, void *arg1, void *arg2, void *arg3);
/**
* spl_invoke_opensbi - boot using a RISC-V OpenSBI image
*/
void spl_invoke_opensbi(struct spl_image_info *spl_image);
/**
* board_return_to_bootrom - allow for boards to continue with the boot ROM
*

View file

@ -1535,16 +1535,14 @@ int fdtdec_setup(void)
puts("Failed to read control FDT\n");
return -1;
}
# elif defined(CONFIG_OF_PRIOR_STAGE)
gd->fdt_blob = (void *)prior_stage_fdt_address;
# endif
# ifndef CONFIG_SPL_BUILD
/* Allow the early environment to override the fdt address */
# if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
gd->fdt_blob = (void *)prior_stage_fdt_address;
# else
gd->fdt_blob = map_sysmem
(env_get_ulong("fdtcontroladdr", 16,
(unsigned long)map_to_sysmem(gd->fdt_blob)), 0);
# endif
# endif
# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)