diff mbox series

[U-Boot,v2,05/11] spl: support booting via RISC-V OpenSBI

Message ID 20190728155723.3412-6-lukas.auer@aisec.fraunhofer.de
State Superseded
Delegated to: Andes
Headers show
Series SPL support for RISC-V | expand

Commit Message

Lukas Auer July 28, 2019, 3:57 p.m. UTC
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.

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 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>
---

Changes in v2: None

 common/image.c           |  1 +
 common/spl/Kconfig       | 17 ++++++++
 common/spl/Makefile      |  1 +
 common/spl/spl.c         |  6 +++
 common/spl/spl_opensbi.c | 85 ++++++++++++++++++++++++++++++++++++++++
 include/image.h          |  1 +
 include/opensbi.h        | 40 +++++++++++++++++++
 include/spl.h            |  5 +++
 8 files changed, 156 insertions(+)
 create mode 100644 common/spl/spl_opensbi.c
 create mode 100644 include/opensbi.h

Comments

Anup Patel July 29, 2019, 8:32 a.m. UTC | #1
On Sun, Jul 28, 2019 at 9:55 PM Lukas Auer
<lukas.auer@aisec.fraunhofer.de> wrote:
>
> 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.
>
> 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 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").

Instead of OpenSBI commit, may be mention that we need OpenSBI v0.4
or higher.

>
> 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>
> ---
>
> Changes in v2: None
>
>  common/image.c           |  1 +
>  common/spl/Kconfig       | 17 ++++++++
>  common/spl/Makefile      |  1 +
>  common/spl/spl.c         |  6 +++
>  common/spl/spl_opensbi.c | 85 ++++++++++++++++++++++++++++++++++++++++
>  include/image.h          |  1 +
>  include/opensbi.h        | 40 +++++++++++++++++++
>  include/spl.h            |  5 +++
>  8 files changed, 156 insertions(+)
>  create mode 100644 common/spl/spl_opensbi.c
>  create mode 100644 include/opensbi.h
>
> diff --git a/common/image.c b/common/image.c
> index 9f9538fac2..7c7353a989 100644
> --- a/common/image.c
> +++ b/common/image.c
> @@ -125,6 +125,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 5d6da5db89..939c8517cd 100644
> --- a/common/spl/Kconfig
> +++ b/common/spl/Kconfig
> @@ -1126,6 +1126,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 d5e3f680f4..1ed4741bdc 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)

Should this be "CONFIG_IS_ENABLED(SPL_OPENSBI)" ?

Am I missing something here ?

> +       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);
> +}
> diff --git a/include/image.h b/include/image.h
> index 5f82194951..78a2dffe54 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -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
> index 0000000000..9f1d62e7dd
> --- /dev/null
> +++ b/include/opensbi.h
> @@ -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
> diff --git a/include/spl.h b/include/spl.h
> index a90f971a23..e4640f3830 100644
> --- a/include/spl.h
> +++ b/include/spl.h
> @@ -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
>   *
> --
> 2.21.0
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> https://lists.denx.de/listinfo/u-boot

Apart from minor queries/comments above, looks good to me.

Reviewed-by: Anup Patel <anup.patel@wdc.com>

Regards,
Anup
Lukas Auer July 29, 2019, 3:51 p.m. UTC | #2
Hi Anup,

On Mon, 2019-07-29 at 14:02 +0530, Anup Patel wrote:
> On Sun, Jul 28, 2019 at 9:55 PM Lukas Auer
> <lukas.auer@aisec.fraunhofer.de> wrote:
> > 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.
> > 
> > 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 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").
> 
> Instead of OpenSBI commit, may be mention that we need OpenSBI v0.4
> or higher.
> 

If there are no other comments on the series I would prefer to keep the
commit message as is, if that is ok for you.
Adding the minimum OpenSBI version is a good idea, however. I can send
a follow-up patch to this series to add the minimum version to the QEMU
board documentation.

> > 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>
> > ---
> > 
> > Changes in v2: None
> > 
> >  common/image.c           |  1 +
> >  common/spl/Kconfig       | 17 ++++++++
> >  common/spl/Makefile      |  1 +
> >  common/spl/spl.c         |  6 +++
> >  common/spl/spl_opensbi.c | 85 ++++++++++++++++++++++++++++++++++++++++
> >  include/image.h          |  1 +
> >  include/opensbi.h        | 40 +++++++++++++++++++
> >  include/spl.h            |  5 +++
> >  8 files changed, 156 insertions(+)
> >  create mode 100644 common/spl/spl_opensbi.c
> >  create mode 100644 include/opensbi.h
> > 
> > diff --git a/common/image.c b/common/image.c
> > index 9f9538fac2..7c7353a989 100644
> > --- a/common/image.c
> > +++ b/common/image.c
> > @@ -125,6 +125,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 5d6da5db89..939c8517cd 100644
> > --- a/common/spl/Kconfig
> > +++ b/common/spl/Kconfig
> > @@ -1126,6 +1126,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 d5e3f680f4..1ed4741bdc 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)
> 
> Should this be "CONFIG_IS_ENABLED(SPL_OPENSBI)" ?
> 
> Am I missing something here ?
> 

The CONFIG_IS_ENABLED(option) macro automatically handles the SPL_*
symbols. On SPL builds, it evaluates to one if CONFIG_SPL_option is
defined. On normal builds, it evaluates to one if CONFIG_option is
defined.

Thanks,
Lukas

> > +       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);
> > +}
> > diff --git a/include/image.h b/include/image.h
> > index 5f82194951..78a2dffe54 100644
> > --- a/include/image.h
> > +++ b/include/image.h
> > @@ -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
> > index 0000000000..9f1d62e7dd
> > --- /dev/null
> > +++ b/include/opensbi.h
> > @@ -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
> > diff --git a/include/spl.h b/include/spl.h
> > index a90f971a23..e4640f3830 100644
> > --- a/include/spl.h
> > +++ b/include/spl.h
> > @@ -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
> >   *
> > --
> > 2.21.0
> > 
> > _______________________________________________
> > U-Boot mailing list
> > U-Boot@lists.denx.de
> > https://lists.denx.de/listinfo/u-boot
> 
> Apart from minor queries/comments above, looks good to me.
> 
> Reviewed-by: Anup Patel <anup.patel@wdc.com>
> 
> Regards,
> Anup
Anup Patel July 30, 2019, 3:45 a.m. UTC | #3
On Mon, Jul 29, 2019 at 9:21 PM Auer, Lukas
<lukas.auer@aisec.fraunhofer.de> wrote:
>
> Hi Anup,
>
> On Mon, 2019-07-29 at 14:02 +0530, Anup Patel wrote:
> > On Sun, Jul 28, 2019 at 9:55 PM Lukas Auer
> > <lukas.auer@aisec.fraunhofer.de> wrote:
> > > 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.
> > >
> > > 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 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").
> >
> > Instead of OpenSBI commit, may be mention that we need OpenSBI v0.4
> > or higher.
> >
>
> If there are no other comments on the series I would prefer to keep the
> commit message as is, if that is ok for you.
> Adding the minimum OpenSBI version is a good idea, however. I can send
> a follow-up patch to this series to add the minimum version to the QEMU
> board documentation.

Sure, please have a separate patch for minimum OpenSBI version. Maybe
you can just update QEMU RISC-V documentation.

>
> > > 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>
> > > ---
> > >
> > > Changes in v2: None
> > >
> > >  common/image.c           |  1 +
> > >  common/spl/Kconfig       | 17 ++++++++
> > >  common/spl/Makefile      |  1 +
> > >  common/spl/spl.c         |  6 +++
> > >  common/spl/spl_opensbi.c | 85 ++++++++++++++++++++++++++++++++++++++++
> > >  include/image.h          |  1 +
> > >  include/opensbi.h        | 40 +++++++++++++++++++
> > >  include/spl.h            |  5 +++
> > >  8 files changed, 156 insertions(+)
> > >  create mode 100644 common/spl/spl_opensbi.c
> > >  create mode 100644 include/opensbi.h
> > >
> > > diff --git a/common/image.c b/common/image.c
> > > index 9f9538fac2..7c7353a989 100644
> > > --- a/common/image.c
> > > +++ b/common/image.c
> > > @@ -125,6 +125,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 5d6da5db89..939c8517cd 100644
> > > --- a/common/spl/Kconfig
> > > +++ b/common/spl/Kconfig
> > > @@ -1126,6 +1126,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 d5e3f680f4..1ed4741bdc 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)
> >
> > Should this be "CONFIG_IS_ENABLED(SPL_OPENSBI)" ?
> >
> > Am I missing something here ?
> >
>
> The CONFIG_IS_ENABLED(option) macro automatically handles the SPL_*
> symbols. On SPL builds, it evaluates to one if CONFIG_SPL_option is
> defined. On normal builds, it evaluates to one if CONFIG_option is
> defined.

Ahh, got it.

Reviewed-by: Anup Patel <anup.patel@wdc.com>

Regards,
Anup
diff mbox series

Patch

diff --git a/common/image.c b/common/image.c
index 9f9538fac2..7c7353a989 100644
--- a/common/image.c
+++ b/common/image.c
@@ -125,6 +125,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 5d6da5db89..939c8517cd 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -1126,6 +1126,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 d5e3f680f4..1ed4741bdc 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);
+}
diff --git a/include/image.h b/include/image.h
index 5f82194951..78a2dffe54 100644
--- a/include/image.h
+++ b/include/image.h
@@ -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
index 0000000000..9f1d62e7dd
--- /dev/null
+++ b/include/opensbi.h
@@ -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
diff --git a/include/spl.h b/include/spl.h
index a90f971a23..e4640f3830 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -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
  *