spl: support booting via RISC-V OpenSBI
authorLukas Auer <lukas.auer@aisec.fraunhofer.de>
Wed, 21 Aug 2019 19:14:44 +0000 (21:14 +0200)
committerAndes <uboot@andestech.com>
Mon, 26 Aug 2019 08:07:42 +0000 (16:07 +0800)
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>
common/image.c
common/spl/Kconfig
common/spl/Makefile
common/spl/spl.c
common/spl/spl_opensbi.c [new file with mode: 0644]
include/image.h
include/opensbi.h [new file with mode: 0644]
include/spl.h

index 84e859a30f455c184ecc4997b584e7c958c5fc4f..645584b5ba2274b7e90b50cc9efc614e175e9a31 100644 (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,             "",             "",                     },
 };
index 660aa66d8498c02f09a7b7c4a3eb270f384df5eb..644a1099429a9aaaafc50d347f3dea18d60d8a8b 100644 (file)
@@ -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
index d28de692dd6a017becc30503d8bace714a6dda20..5ce6f4ae480c9882f5d4e1c274831ad08105efd9 100644 (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
index 2c696f2a79c9304c6eaa8f1a2279836148efa3b1..8c9415bedf597d299ee859f4a1fd821578204ea0 100644 (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");
diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c
new file mode 100644 (file)
index 0000000..a6b4480
--- /dev/null
@@ -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);
+}
index 27d7cb9d1e8923d885e712fa160959c2a75a3044..404b7338e6a7d699c83e7cf8de3fba69b2b75c75 100644 (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,
 };
diff --git a/include/opensbi.h b/include/opensbi.h
new file mode 100644 (file)
index 0000000..9f1d62e
--- /dev/null
@@ -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
index a90f971a2393eae6171ae001b723e8e62e1a41d5..e4640f3830b04a7adfbcdd259b1aac047eb7bde4 100644 (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
  *