[PATCH 4/5] sandbox: implement reset

Simon Glass sjg at chromium.org
Tue Oct 27 05:52:27 CET 2020


Hi Heinrich,

On Sun, 25 Oct 2020 at 00:04, Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
>
> Up to now the sandbox would shutdown upon a cold reset request. Instead it
> should be reset.
>
> In our coding we use static variables. The only safe way to return to an
> initial state is to relaunch the U-Boot binary.

This is unfortunate, but I suspect you may be right. Have you looked at it?

>
> The reset implementation uses a longjmp() to return to the main() function
> and then relaunches U-Boot using execv().
>
> Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
> ---
>  arch/sandbox/cpu/os.c                     | 14 ++++++++++++++
>  arch/sandbox/cpu/start.c                  | 22 ++++++++++++++++++++++
>  arch/sandbox/cpu/state.c                  |  1 +
>  arch/sandbox/include/asm/u-boot-sandbox.h |  3 +++
>  drivers/sysreset/sysreset_sandbox.c       |  3 +++
>  include/os.h                              |  5 +++++
>  6 files changed, 48 insertions(+)
>
> diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
> index c461fb0db0..ed044e87fb 100644
> --- a/arch/sandbox/cpu/os.c
> +++ b/arch/sandbox/cpu/os.c
> @@ -817,3 +817,17 @@ void *os_find_text_base(void)
>
>         return base;
>  }
> +
> +void os_relaunch(int argc, char *argv[])
> +{
> +       char **args;
> +
> +       args = calloc(argc + 1, sizeof(char *));
> +       if (!args)
> +               goto out;
> +       memcpy(args, argv, sizeof(char *) * argc);
> +       args[argc] = NULL;
> +       execv(args[0], args);
> +out:
> +       os_exit(1);
> +}
> diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
> index c6a2bbe468..ee1d4b9581 100644
> --- a/arch/sandbox/cpu/start.c
> +++ b/arch/sandbox/cpu/start.c
> @@ -5,6 +5,7 @@
>
>  #include <common.h>
>  #include <command.h>
> +#include <dm/root.h>

Put before linux/ below

>  #include <errno.h>
>  #include <init.h>
>  #include <os.h>
> @@ -14,11 +15,15 @@
>  #include <asm/io.h>
>  #include <asm/malloc.h>
>  #include <asm/sections.h>
> +#include <asm/setjmp.h>
>  #include <asm/state.h>
>  #include <linux/ctype.h>
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +/* longjmp buffer for reset */
> +static struct jmp_buf_data reset_jmp;
> +
>  /* Compare two options so that they can be sorted into alphabetical order */
>  static int h_compare_opt(const void *p1, const void *p2)
>  {
> @@ -394,12 +399,29 @@ void state_show(struct sandbox_state *state)
>         printf("\n");
>  }
>
> +void sandbox_reset(void)
> +{
> +       /* Do this here while it still has an effect */
> +       os_fd_restore();
> +       if (state_uninit())
> +               os_exit(2);
> +
> +       if (dm_uninit())
> +               os_exit(2);
> +
> +       /* This is considered normal termination for now */
> +       longjmp(&reset_jmp, 1);
> +}
> +
>  int main(int argc, char *argv[])
>  {
>         struct sandbox_state *state;
>         gd_t data;
>         int ret;
>
> +       if (setjmp(&reset_jmp))
> +               os_relaunch(argc, argv);
> +
>         memset(&data, '\0', sizeof(data));
>         gd = &data;
>         gd->arch.text_base = os_find_text_base();
> diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
> index 34b6fff7e7..59f37fab0b 100644
> --- a/arch/sandbox/cpu/state.c
> +++ b/arch/sandbox/cpu/state.c
> @@ -358,6 +358,7 @@ void state_reset_for_test(struct sandbox_state *state)
>         /* No reset yet, so mark it as such. Always allow power reset */
>         state->last_sysreset = SYSRESET_COUNT;
>         state->sysreset_allowed[SYSRESET_POWER_OFF] = true;
> +       state->sysreset_allowed[SYSRESET_COLD] = true;
>         state->allow_memio = false;
>
>         memset(&state->wdt, '\0', sizeof(state->wdt));
> diff --git a/arch/sandbox/include/asm/u-boot-sandbox.h b/arch/sandbox/include/asm/u-boot-sandbox.h
> index 798d003077..b1bdcbcde5 100644
> --- a/arch/sandbox/include/asm/u-boot-sandbox.h
> +++ b/arch/sandbox/include/asm/u-boot-sandbox.h
> @@ -84,6 +84,9 @@ void sandbox_set_enable_pci_map(int enable);
>   */
>  int sandbox_read_fdt_from_file(void);
>
> +/* Reset sandbox */

I think this needs a better comment, explaining how it resets.

> +void sandbox_reset(void);
> +
>  /* Exit sandbox (quit U-Boot) */
>  void sandbox_exit(void);
>
> diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c
> index 69c22a7000..c92132798c 100644
> --- a/drivers/sysreset/sysreset_sandbox.c
> +++ b/drivers/sysreset/sysreset_sandbox.c
> @@ -56,6 +56,9 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
>         switch (type) {
>         case SYSRESET_COLD:
>                 state->last_sysreset = type;
> +               if (!state->sysreset_allowed[type])
> +                       return -EACCES;
> +               sandbox_reset();
>                 break;
>         case SYSRESET_POWER_OFF:
>                 state->last_sysreset = type;
> diff --git a/include/os.h b/include/os.h
> index 1874ae674f..187dbf06f2 100644
> --- a/include/os.h
> +++ b/include/os.h
> @@ -355,4 +355,9 @@ int os_read_file(const char *name, void **bufp, int *sizep);
>   */
>  void *os_find_text_base(void);
>
> +/**
> + * os_relaunch() - restart the sandbox

again I think a bit more detail would help

> + */
> +void os_relaunch(int argc, char *argv[]);
> +
>  #endif
> --
> 2.28.0
>

Regards,
Simon


More information about the U-Boot mailing list