[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