summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorLukas Auer <lukas.auer@aisec.fraunhofer.de>2019-08-21 22:14:44 +0300
committerAndes <uboot@andestech.com>2019-08-26 11:07:42 +0300
commit5e30e45c83264841018dc8135034426fd0c0f857 (patch)
tree87054cf4d9db17ca06e610b6325c8a6138d5c29c /common
parentfbfd92bf9bdc39d6537806ab58a83a48e5a2c004 (diff)
downloadu-boot-5e30e45c83264841018dc8135034426fd0c0f857.tar.xz
spl: support booting via RISC-V OpenSBI
RISC-V OpenSBI is an open-source implementation of the RISC-V Supervisor Binary Interface (SBI) specification. It is required by Linux and U-Boot running in supervisor mode. This patch adds support for booting via the OpenSBI FW_DYNAMIC firmware. It supports OpenSBI version 0.4 and higher. In this configuration, U-Boot SPL starts in machine mode. After loading OpenSBI and U-Boot proper, it will start OpenSBI. All necessary parameters are generated by U-Boot SPL and are passed to OpenSBI. U-Boot proper is started in supervisor mode by OpenSBI. Support for OpenSBI is enabled with CONFIG_SPL_OPENSBI. An additional configuration entry, CONFIG_SPL_OPENSBI_LOAD_ADDR, is used to specify the load address of the OpenSBI firmware binary. It is not used directly in U-Boot and instead is intended to make the value available to scripts such as FIT configuration generators. The header file include/opensbi.h is based on header files from the OpenSBI project. They are recent, as of commit bae54f764570 ("firmware: Add fw_dynamic firmware"). Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Tested-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Anup Patel <anup.patel@wdc.com>
Diffstat (limited to 'common')
-rw-r--r--common/image.c1
-rw-r--r--common/spl/Kconfig17
-rw-r--r--common/spl/Makefile1
-rw-r--r--common/spl/spl.c6
-rw-r--r--common/spl/spl_opensbi.c85
5 files changed, 110 insertions, 0 deletions
diff --git a/common/image.c b/common/image.c
index 84e859a30f..645584b5ba 100644
--- a/common/image.c
+++ b/common/image.c
@@ -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, "", "", },
};
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 660aa66d84..644a109942 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1148,6 +1148,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
diff --git a/common/spl/Makefile b/common/spl/Makefile
index d28de692dd..5ce6f4ae48 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -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
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 2c696f2a79..8c9415bedf 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -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");
diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c
new file mode 100644
index 0000000000..a6b4480ed2
--- /dev/null
+++ b/common/spl/spl_opensbi.c
@@ -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);
+}